New Feature Examples, Corrections & Rewrites

This commit is contained in:
Bruce Eckel 2021-11-07 17:48:46 -07:00
parent 0fedf43178
commit cab823f881
31 changed files with 782 additions and 379 deletions

View File

@ -8,6 +8,7 @@ includes tests to verify that the code in the book is correct.
> NOTE: Do not attempt to use JDK 16 or greater with gradle. > NOTE: Do not attempt to use JDK 16 or greater with gradle.
> This produces a `BUG!` message from Gradle, which is broken for those versions. > This produces a `BUG!` message from Gradle, which is broken for those versions.
> To test new Java features in JDK 16 or 17 you must compile and run those examples by hand.
## Contents ## Contents

View File

@ -4,49 +4,29 @@
// Visit http://OnJava8.com for more book information. // Visit http://OnJava8.com for more book information.
// Demonstrates WeakHashMap // Demonstrates WeakHashMap
import java.util.*; import java.util.*;
import java.util.stream.*;
class Element {
private String ident;
Element(String id) { ident = id; }
@Override public String toString() { return ident; }
@Override public int hashCode() {
return Objects.hashCode(ident);
}
@Override public boolean equals(Object r) {
return r instanceof Element &&
Objects.equals(ident, ((Element)r).ident);
}
@SuppressWarnings("deprecation")
@Override protected void finalize() {
System.out.println("Finalizing " +
getClass().getSimpleName() + " " + ident);
}
}
class Key extends Element {
Key(String id) { super(id); }
}
class Value extends Element {
Value(String id) { super(id); }
}
public class CanonicalMapping { public class CanonicalMapping {
static void showKeys(Map<String, String> m) {
// Display sorted keys
List<String> keys = new ArrayList<>(m.keySet());
Collections.sort(keys);
System.out.println(keys);
}
public static void main(String[] args) { public static void main(String[] args) {
int size = 1000; int size = 100;
// Or, choose size via the command line: String[] savedKeys = new String[size];
if(args.length > 0) WeakHashMap<String,String> map =
size = Integer.valueOf(args[0]);
Key[] keys = new Key[size];
WeakHashMap<Key,Value> map =
new WeakHashMap<>(); new WeakHashMap<>();
for(int i = 0; i < size; i++) { for(int i = 0; i < size; i++) {
Key k = new Key(Integer.toString(i)); String key = String.format("%03d", i);
Value v = new Value(Integer.toString(i)); String value = Integer.toString(i);
if(i % 3 == 0) if(i % 3 == 0)
keys[i] = k; // Save as "real" references savedKeys[i] = key; // Save as "real" references
map.put(k, v); map.put(key, value);
} }
showKeys(map);
System.gc(); System.gc();
showKeys(map);
} }
} }

View File

@ -13,9 +13,9 @@ public class ListSortSearch {
System.out.println(list); System.out.println(list);
Collections.shuffle(list, new Random(47)); Collections.shuffle(list, new Random(47));
System.out.println("Shuffled: " + list); System.out.println("Shuffled: " + list);
// Use ListIterator to trim off last elements: ListIterator<String> it =
ListIterator<String> it = list.listIterator(10); list.listIterator(10); // [1]
while(it.hasNext()) { while(it.hasNext()) { // [2]
it.next(); it.next();
it.remove(); it.remove();
} }

View File

@ -15,7 +15,7 @@ public class QueueBehavior {
} }
static void test(int id, Queue<String> queue) { static void test(int id, Queue<String> queue) {
System.out.print(id + ": "); System.out.print(id + ": ");
strings().map(queue::offer).count(); strings().forEach(queue::offer);
while(queue.peek() != null) while(queue.peek() != null)
System.out.print(queue.remove() + " "); System.out.print(queue.remove() + " ");
System.out.println(); System.out.println();

View File

@ -1,5 +1,5 @@
0: main 0: main
1: ForkJoinPool.commonPool-worker-2 1: main
2: main 2: main
3: main 3: main
4: main 4: main
@ -8,249 +8,3 @@
7: main 7: main
8: main 8: main
9: main 9: main
10: main
11: main
12: main
13: main
14: main
15: main
16: main
17: main
18: main
19: main
20: main
21: main
22: main
23: main
24: main
25: main
26: main
27: main
28: main
29: main
30: main
31: main
32: main
33: main
34: main
35: main
36: main
37: main
38: main
39: main
40: main
41: main
42: main
43: main
44: main
45: main
46: main
47: main
48: main
49: main
50: main
51: main
52: main
53: main
54: main
55: main
56: main
57: main
58: main
59: main
60: main
61: main
62: main
63: main
64: main
65: main
66: main
67: main
68: main
69: main
70: main
71: main
72: main
73: main
74: main
75: main
76: main
77: main
78: main
79: main
80: main
81: main
82: main
83: main
84: main
85: main
86: main
87: main
88: main
89: main
90: main
91: main
92: main
93: main
94: main
95: main
96: main
97: main
98: main
99: main
100: main
101: main
102: main
103: main
104: main
105: main
106: main
107: main
108: main
108: ForkJoinPool.commonPool-worker-2
109: ForkJoinPool.commonPool-worker-2
110: ForkJoinPool.commonPool-worker-2
111: ForkJoinPool.commonPool-worker-2
112: ForkJoinPool.commonPool-worker-2
113: ForkJoinPool.commonPool-worker-2
114: ForkJoinPool.commonPool-worker-2
115: ForkJoinPool.commonPool-worker-2
116: ForkJoinPool.commonPool-worker-2
117: ForkJoinPool.commonPool-worker-2
118: ForkJoinPool.commonPool-worker-2
119: ForkJoinPool.commonPool-worker-2
120: ForkJoinPool.commonPool-worker-2
121: ForkJoinPool.commonPool-worker-2
122: ForkJoinPool.commonPool-worker-2
123: ForkJoinPool.commonPool-worker-2
124: ForkJoinPool.commonPool-worker-2
125: ForkJoinPool.commonPool-worker-2
126: ForkJoinPool.commonPool-worker-2
127: ForkJoinPool.commonPool-worker-2
128: ForkJoinPool.commonPool-worker-2
129: ForkJoinPool.commonPool-worker-2
130: ForkJoinPool.commonPool-worker-2
131: ForkJoinPool.commonPool-worker-2
132: ForkJoinPool.commonPool-worker-2
133: ForkJoinPool.commonPool-worker-2
134: ForkJoinPool.commonPool-worker-2
135: ForkJoinPool.commonPool-worker-2
136: ForkJoinPool.commonPool-worker-2
137: ForkJoinPool.commonPool-worker-2
138: ForkJoinPool.commonPool-worker-2
139: ForkJoinPool.commonPool-worker-2
140: ForkJoinPool.commonPool-worker-2
141: ForkJoinPool.commonPool-worker-2
142: ForkJoinPool.commonPool-worker-2
143: ForkJoinPool.commonPool-worker-2
144: ForkJoinPool.commonPool-worker-2
145: ForkJoinPool.commonPool-worker-2
146: ForkJoinPool.commonPool-worker-2
147: ForkJoinPool.commonPool-worker-2
148: ForkJoinPool.commonPool-worker-2
149: ForkJoinPool.commonPool-worker-2
150: ForkJoinPool.commonPool-worker-2
151: ForkJoinPool.commonPool-worker-2
152: ForkJoinPool.commonPool-worker-2
153: ForkJoinPool.commonPool-worker-2
154: ForkJoinPool.commonPool-worker-2
155: ForkJoinPool.commonPool-worker-2
156: ForkJoinPool.commonPool-worker-2
157: ForkJoinPool.commonPool-worker-2
158: ForkJoinPool.commonPool-worker-2
159: ForkJoinPool.commonPool-worker-2
160: ForkJoinPool.commonPool-worker-2
161: ForkJoinPool.commonPool-worker-2
162: ForkJoinPool.commonPool-worker-2
163: ForkJoinPool.commonPool-worker-2
164: ForkJoinPool.commonPool-worker-2
165: ForkJoinPool.commonPool-worker-2
166: ForkJoinPool.commonPool-worker-2
167: ForkJoinPool.commonPool-worker-2
168: ForkJoinPool.commonPool-worker-2
169: ForkJoinPool.commonPool-worker-2
170: ForkJoinPool.commonPool-worker-2
171: ForkJoinPool.commonPool-worker-2
172: ForkJoinPool.commonPool-worker-2
173: ForkJoinPool.commonPool-worker-2
174: ForkJoinPool.commonPool-worker-2
175: ForkJoinPool.commonPool-worker-2
176: ForkJoinPool.commonPool-worker-2
177: ForkJoinPool.commonPool-worker-2
178: ForkJoinPool.commonPool-worker-2
179: ForkJoinPool.commonPool-worker-2
180: ForkJoinPool.commonPool-worker-2
181: ForkJoinPool.commonPool-worker-2
182: ForkJoinPool.commonPool-worker-2
183: ForkJoinPool.commonPool-worker-2
184: ForkJoinPool.commonPool-worker-2
185: ForkJoinPool.commonPool-worker-2
186: ForkJoinPool.commonPool-worker-2
187: ForkJoinPool.commonPool-worker-2
188: ForkJoinPool.commonPool-worker-2
189: ForkJoinPool.commonPool-worker-2
190: ForkJoinPool.commonPool-worker-2
191: ForkJoinPool.commonPool-worker-2
192: ForkJoinPool.commonPool-worker-2
193: ForkJoinPool.commonPool-worker-2
194: ForkJoinPool.commonPool-worker-2
195: ForkJoinPool.commonPool-worker-2
196: ForkJoinPool.commonPool-worker-2
197: ForkJoinPool.commonPool-worker-2
198: ForkJoinPool.commonPool-worker-2
199: ForkJoinPool.commonPool-worker-2
200: ForkJoinPool.commonPool-worker-2
201: ForkJoinPool.commonPool-worker-2
202: ForkJoinPool.commonPool-worker-2
203: ForkJoinPool.commonPool-worker-2
204: ForkJoinPool.commonPool-worker-2
205: ForkJoinPool.commonPool-worker-2
206: ForkJoinPool.commonPool-worker-2
207: ForkJoinPool.commonPool-worker-2
208: ForkJoinPool.commonPool-worker-2
209: ForkJoinPool.commonPool-worker-2
210: ForkJoinPool.commonPool-worker-2
211: ForkJoinPool.commonPool-worker-2
212: ForkJoinPool.commonPool-worker-2
213: ForkJoinPool.commonPool-worker-2
214: ForkJoinPool.commonPool-worker-2
215: ForkJoinPool.commonPool-worker-2
216: ForkJoinPool.commonPool-worker-2
217: ForkJoinPool.commonPool-worker-2
218: ForkJoinPool.commonPool-worker-2
219: ForkJoinPool.commonPool-worker-2
220: ForkJoinPool.commonPool-worker-2
221: ForkJoinPool.commonPool-worker-2
222: ForkJoinPool.commonPool-worker-2
223: ForkJoinPool.commonPool-worker-2
224: ForkJoinPool.commonPool-worker-2
225: ForkJoinPool.commonPool-worker-2
226: ForkJoinPool.commonPool-worker-2
227: ForkJoinPool.commonPool-worker-2
228: ForkJoinPool.commonPool-worker-2
229: ForkJoinPool.commonPool-worker-2
230: ForkJoinPool.commonPool-worker-2
231: ForkJoinPool.commonPool-worker-2
232: ForkJoinPool.commonPool-worker-2
233: ForkJoinPool.commonPool-worker-2
234: ForkJoinPool.commonPool-worker-2
236: main
237: main
238: main
239: main
240: main
241: main
242: main
243: main
244: main
245: main
246: main
247: main
248: main
249: main
250: main
251: main
252: main
253: main
254: main
255: main

View File

@ -0,0 +1,42 @@
// enumerations/ArrowInSwitch.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Since JDK 14
import static java.util.stream.IntStream.range;
public class ArrowInSwitch {
static void colons(int i) {
switch(i) {
case 1: System.out.println("one");
break;
case 2: System.out.println("two");
break;
case 3: System.out.println("three");
break;
default: System.out.println("default");
}
}
static void arrows(int i) {
switch(i) {
case 1 -> System.out.println("one");
case 2 -> System.out.println("two");
case 3 -> System.out.println("three");
default -> System.out.println("default");
}
}
public static void main(String[] args) {
range(0, 4).forEach(i -> colons(i));
range(0, 4).forEach(i -> arrows(i));
}
}
/* Output:
default
one
two
three
default
one
two
three
*/

View File

@ -0,0 +1,92 @@
// enumerations/CaseNull.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
// Run with java flag: --enable-preview
import java.util.*;
import java.util.function.*;
public class CaseNull {
static void old(String s) {
if(s == null) {
System.out.println("null");
return;
}
switch(s) {
case "XX" -> System.out.println("XX");
default -> System.out.println("default");
}
}
static void checkNull(String s) {
switch(s) {
case "XX" -> System.out.println("XX");
case null -> System.out.println("null");
default -> System.out.println("default");
}
// Works with colon syntax, too:
switch(s) {
case "XX": System.out.println("XX");
break;
case null: System.out.println("null");
break;
default : System.out.println("default");
}
}
static void defaultOnly(String s) {
switch(s) {
case "XX" -> System.out.println("XX");
default -> System.out.println("default");
}
}
static void combineNullAndCase(String s) {
switch(s) {
case "XX", null -> System.out.println("XX|null");
default -> System.out.println("default");
}
}
static void combineNullAndDefault(String s) {
switch(s) {
case "XX" -> System.out.println("XX");
case null, default -> System.out.println("both");
}
}
static void test(Consumer<String> cs) {
cs.accept("XX");
cs.accept("YY");
try {
cs.accept(null);
} catch(NullPointerException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
test(CaseNull::old);
test(CaseNull::checkNull);
test(CaseNull::defaultOnly);
test(CaseNull::combineNullAndCase);
test(CaseNull::combineNullAndDefault);
}
}
/* Output:
XX
default
null
XX
XX
default
default
null
null
XX
default
Cannot invoke "String.hashCode()" because "<local1>" is null
XX|null
default
XX|null
XX
both
both
*/

View File

@ -0,0 +1,20 @@
// enumerations/Dominance.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
import java.util.*;
sealed interface Base {}
record Derived() implements Base {}
public class Dominance {
static String test(Base base) {
return switch(base) {
case Derived d -> "Derived";
case Base b -> "B"; // [1]
};
}
}

View File

@ -0,0 +1,17 @@
// enumerations/EnumSwitch.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Since JDK 14
public class EnumSwitch {
enum Signal { GREEN, YELLOW, RED, }
Signal color = Signal.RED;
public void change() {
color = switch(color) {
case RED -> Signal.GREEN;
case GREEN -> Signal.YELLOW;
case YELLOW -> Signal.RED;
};
}
}

View File

@ -0,0 +1,40 @@
// enumerations/NormalLiskov.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
import java.util.stream.*;
interface LifeForm {
String move();
String react();
}
class Worm implements LifeForm {
@Override public String move() {
return "Worm::move()";
}
@Override public String react() {
return "Worm::react()";
}
}
class Giraffe implements LifeForm {
@Override public String move() {
return "Giraffe::move()";
}
@Override public String react() {
return "Giraffe::react()";
}
}
public class NormalLiskov {
public static void main(String[] args) {
Stream.of(new Worm(), new Giraffe())
.forEach(lf -> System.out.println(
lf.move() + " " + lf.react()));
}
}
/* Output:
Worm::move() Worm::react()
Giraffe::move() Giraffe::react()
*/

View File

@ -0,0 +1,46 @@
// enumerations/ObjectMatch.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
// Run with java flag: --enable-preview
import java.util.*;
record XX() {}
public class ObjectMatch {
static String match(Object o) {
return switch(o) {
case Dog d -> "Walk the dog";
case Fish f -> "Change the fish water";
case Pet sp -> "Not dog or fish";
case String s -> "String " + s;
case Integer i -> "Integer " + i;
case String[] sa -> String.join(", ", sa);
case null, XX xx -> "null or XX: " + xx;
default -> "Something else";
};
}
public static void main(String[] args) {
List.of(new Dog(), new Fish(), new Pet(),
"Oscar", Integer.valueOf(12),
Double.valueOf("47.74"),
new String[]{ "to", "the", "point" },
new XX()
).forEach(
p -> System.out.println(match(p))
);
}
}
/* Output:
Walk the dog
Change the fish water
Not dog or fish
String Oscar
Integer 12
Something else
to, the, point
null or Object: XX[]
*/

View File

@ -0,0 +1,27 @@
// enumerations/OddScoping.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Since JDK 16
public class OddScoping {
static void f(Object o) {
if(!(o instanceof String s)) {
System.out.println("Not a String");
throw new RuntimeException();
}
// s is in scope here!
System.out.println(s.toUpperCase()); // [1]
}
public static void main(String[] args) {
f("Curiouser and Curiouser");
f(null);
}
}
/* Output:
CURIOUSER AND CURIOUSER
Not a String
Exception in thread "main" java.lang.RuntimeException
at OddScoping.f(OddScoping.java:8)
at OddScoping.main(OddScoping.java:15)
*/

46
enumerations/People.java Normal file
View File

@ -0,0 +1,46 @@
// enumerations/People.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
// Run with java flag: --enable-preview
import java.util.*;
record Person(String name, int age) {}
public class People {
static String categorize(Person person) {
return switch(person) {
case Person p && p.age() > 40 // [1]
-> p + " is middle aged";
case Person p &&
(p.name().contains("D") || p.age() == 14)
-> p + " D or 14";
case Person p && !(p.age() >= 100) // [2]
-> p + " is not a centenarian";
case Person p -> p + " Everyone else";
};
}
public static void main(String[] args) {
List.of(
new Person("Dorothy", 15),
new Person("John Bigboote", 42),
new Person("Morty", 14),
new Person("Morty Jr.", 1),
new Person("Jose", 39),
new Person("Kane", 118)
).forEach(
p -> System.out.println(categorize(p))
);
}
}
/* Output:
Person[name=Dorothy, age=15] D or 14
Person[name=John Bigboote, age=42] is middle aged
Person[name=Morty, age=14] D or 14
Person[name=Morty Jr., age=1] is not a centenarian
Person[name=Jose, age=39] is not a centenarian
Person[name=Kane, age=118] is middle aged
*/

16
enumerations/Pet.java Normal file
View File

@ -0,0 +1,16 @@
// enumerations/Pet.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
public class Pet {
void feed() {}
}
class Dog extends Pet {
void walk() {}
}
class Fish extends Pet {
void changeWater() {}
}

View File

@ -0,0 +1,22 @@
// enumerations/PetPatternMatch.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
import java.util.*;
public class PetPatternMatch {
static void careFor(Pet p) {
switch(p) {
case Dog d -> d.walk();
case Fish f -> f.changeWater();
case Pet sp -> sp.feed();
};
}
static void petCare() {
List.of(new Dog(), new Fish())
.forEach(p -> careFor(p));
}
}

View File

@ -0,0 +1,36 @@
// enumerations/PetPatternMatch2.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
package sealedpet;
import java.util.*;
sealed interface Pet {
void feed();
}
final class Dog implements Pet {
@Override public void feed() {}
void walk() {}
}
final class Fish implements Pet {
@Override public void feed() {}
void changeWater() {}
}
public class PetPatternMatch2 {
static void careFor(Pet p) {
switch(p) {
case Dog d -> d.walk();
case Fish f -> f.changeWater();
};
}
static void petCare() {
List.of(new Dog(), new Fish())
.forEach(p -> careFor(p));
}
}

36
enumerations/Planets.java Normal file
View File

@ -0,0 +1,36 @@
// enumerations/Planets.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Since JDK 14
enum CelestialBody {
MERCURY, VENUS, EARTH, MARS, JUPITER,
SATURN, URANUS, NEPTUNE, PLUTO
}
public class Planets {
public static String classify(CelestialBody b) {
var result = switch(b) {
case MERCURY, VENUS, EARTH,
MARS, JUPITER,
SATURN, URANUS, NEPTUNE -> {
System.out.print("A planet: ");
yield b.toString();
}
case PLUTO -> {
System.out.print("Not a planet: ");
yield b.toString();
}
};
return result;
}
public static void main(String[] args) {
System.out.println(classify(CelestialBody.MARS));
System.out.println(classify(CelestialBody.PLUTO));
}
}
/* Output:
A planet: MARS
Not a planet: PLUTO
*/

View File

@ -0,0 +1,48 @@
// enumerations/SealedPatternMatch.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
// Run with java flag: --enable-preview
import java.util.*;
sealed interface Transport {};
record Bicycle(String id) implements Transport {};
record Glider(int size) implements Transport {};
record Surfboard(double weight) implements Transport {};
// If you uncomment this:
// record Skis(int length) implements Transport {};
// You get an error: "the switch expression
// does not cover all possible input values"
public class SealedPatternMatch {
static String exhaustive(Transport t) {
return switch(t) {
case Bicycle b -> "Bicycle " + b.id();
case Glider g -> "Glider " + g.size();
case Surfboard s -> "Surfboard " + s.weight();
};
}
public static void main(String[] args) {
List.of(
new Bicycle("Bob"),
new Glider(65),
new Surfboard(6.4)
).forEach(
t -> System.out.println(exhaustive(t))
);
try {
exhaustive(null); // Always possible! // [1]
} catch(NullPointerException e) {
System.out.println("Not exhaustive: " + e);
}
}
}
/* Output:
Bicycle Bob
Glider 65
Surfboard 6.4
Not exhaustive: java.lang.NullPointerException
*/

53
enumerations/Shapes.java Normal file
View File

@ -0,0 +1,53 @@
// enumerations/Shapes.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
// Run with java flag: --enable-preview
import java.util.*;
sealed interface Shape {
double area();
}
record Circle(double radius) implements Shape {
@Override public double area() {
return Math.PI * radius * radius;
}
}
record Rectangle(double side1, double side2)
implements Shape {
@Override public double area() {
return side1 * side2;
}
}
public class Shapes {
static void classify(Shape s) {
System.out.println(switch(s) {
case Circle c && c.area() < 100.0
-> "Small Circle: " + c;
case Circle c -> "Large Circle: " + c;
case Rectangle r && r.side1() == r.side2()
-> "Square: " + r;
case Rectangle r -> "Rectangle: " + r;
});
}
public static void main(String[] args) {
List.of(
new Circle(5.0),
new Circle(25.0),
new Rectangle(12.0, 12.0),
new Rectangle(12.0, 15.0)
).forEach(t -> classify(t));
}
}
/* Output:
Small Circle: Circle[radius=5.0]
Large Circle: Circle[radius=25.0]
Square: Rectangle[side1=12.0, side2=12.0]
Rectangle: Rectangle[side1=12.0, side2=15.0]
*/

View File

@ -0,0 +1,36 @@
// enumerations/SmartCasting.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Since JDK 16
public class SmartCasting {
static void dumb(Object x) {
if(x instanceof String) {
String s = (String)x;
if(s.length() > 0) {
System.out.format(
"%d %s%n", s.length(), s.toUpperCase());
}
}
}
static void smart(Object x) {
if(x instanceof String s && s.length() > 0) {
System.out.format(
"%d %s%n", s.length(), s.toUpperCase());
}
}
static void wrong(Object x) {
// "Or" never works:
// if(x instanceof String s || s.length() > 0) {}
// error: cannot find symbol ^
}
public static void main(String[] args) {
dumb("dumb");
smart("smart");
}
}
/* Output:
4 DUMB
5 SMART
*/

View File

@ -0,0 +1,38 @@
// enumerations/SwitchExpression.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Since JDK 14
import java.util.*;
public class SwitchExpression {
static int colon(String s) {
var result = switch(s) {
case "i": yield 1;
case "j": yield 2;
case "k": yield 3;
default: yield 0;
};
return result;
}
static int arrow(String s) {
var result = switch(s) {
case "i" -> 1;
case "j" -> 2;
case "k" -> 3;
default -> 0;
};
return result;
}
public static void main(String[] args) {
for(var s: new String[]{"i", "j", "k", "z"})
System.out.format(
"%s %d %d%n", s, colon(s), arrow(s));
}
}
/* Output:
i 1 1
j 2 2
k 3 3
z 0 0
*/

47
enumerations/Tanks.java Normal file
View File

@ -0,0 +1,47 @@
// enumerations/Tanks.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {NewFeature} Preview in JDK 17
// Compile with javac flags:
// --enable-preview --source 17
// Run with java flag: --enable-preview
import java.util.*;
enum Type { TOXIC, FLAMMABLE, NEUTRAL }
record Level(int percent) {
Level {
if(percent < 0 || percent > 100)
throw new IndexOutOfBoundsException(
percent + " percent");
}
}
record Tank(Type type, Level level) {}
public class Tanks {
static String check(Tank tank) {
return switch(tank) {
case Tank t && t.type() == Type.TOXIC
-> "Toxic: " + t;
case Tank t && ( // [1]
t.type() == Type.TOXIC &&
t.level().percent() < 50
) -> "Toxic, low: " + t;
case Tank t && t.type() == Type.FLAMMABLE
-> "Flammable: " + t;
// Equivalent to "default":
case Tank t -> "Other Tank: " + t;
};
}
public static void main(String[] args) {
List.of(
new Tank(Type.TOXIC, new Level(49)),
new Tank(Type.FLAMMABLE, new Level(52)),
new Tank(Type.NEUTRAL, new Level(75))
).forEach(
t -> System.out.println(check(t))
);
}
}

View File

@ -10,7 +10,7 @@ public class ForTypeInference {
System.out.println(s); System.out.println(s);
} }
} }
/* Ouput: /* Output:
NOT NOT
MILD MILD
MEDIUM MEDIUM

View File

@ -9,7 +9,7 @@ public class Range {
// Produce sequence [start..end) incrementing by step // Produce sequence [start..end) incrementing by step
public static public static
int[] range(int start, int end, int step) { int[] range(int start, int end, int step) {
if (step == 0) if(step == 0)
throw new throw new
IllegalArgumentException("Step cannot be zero"); IllegalArgumentException("Step cannot be zero");
int sz = Math.max(0, step >= 0 ? int sz = Math.max(0, step >= 0 ?

View File

@ -11,49 +11,37 @@ enum Color { RED, BLUE, GREEN }
abstract class Shape implements Serializable { abstract class Shape implements Serializable {
private int xPos, yPos, dimension; private int xPos, yPos, dimension;
private static Random rand = new Random(47);
private static int counter = 0;
public abstract void setColor(Color newColor);
public abstract Color getColor();
Shape(int xVal, int yVal, int dim) { Shape(int xVal, int yVal, int dim) {
xPos = xVal; xPos = xVal;
yPos = yVal; yPos = yVal;
dimension = dim; dimension = dim;
} }
public abstract void setColor(Color newColor);
public abstract Color getColor();
@Override public String toString() { @Override public String toString() {
return getClass() + "Color[" + getColor() + return "\n" + getClass() + " " + getColor() +
"] xPos[" + xPos + "] yPos[" + yPos + " xPos[" + xPos + "] yPos[" + yPos +
"] dim[" + dimension + "]\n"; "] dim[" + dimension + "]";
} }
private static Random rand = new Random(47);
private static int counter = 0;
public static Shape randomFactory() { public static Shape randomFactory() {
int xVal = rand.nextInt(100); int xVal = rand.nextInt(100);
int yVal = rand.nextInt(100); int yVal = rand.nextInt(100);
int dim = rand.nextInt(100); int dim = rand.nextInt(100);
switch(counter++ % 3) { switch(counter++ % 2) {
default: default:
case 0: return new Circle(xVal, yVal, dim); case 0: return new Circle(xVal, yVal, dim);
case 1: return new Square(xVal, yVal, dim); case 1: return new Line(xVal, yVal, dim);
case 2: return new Line(xVal, yVal, dim);
} }
} }
} }
class Circle extends Shape { class Circle extends Shape {
private static Color color = Color.RED;
Circle(int xVal, int yVal, int dim) { Circle(int xVal, int yVal, int dim) {
super(xVal, yVal, dim); super(xVal, yVal, dim);
} }
@Override public void setColor(Color newColor) {
color = newColor;
}
@Override public Color getColor() { return color; }
}
class Square extends Shape {
private static Color color = Color.RED; private static Color color = Color.RED;
Square(int xVal, int yVal, int dim) {
super(xVal, yVal, dim);
}
@Override public void setColor(Color newColor) { @Override public void setColor(Color newColor) {
color = newColor; color = newColor;
} }
@ -61,35 +49,36 @@ class Square extends Shape {
} }
class Line extends Shape { class Line extends Shape {
Line(int xVal, int yVal, int dim) {
super(xVal, yVal, dim);
}
private static Color color = Color.RED; private static Color color = Color.RED;
@Override public void setColor(Color newColor) {
color = newColor;
}
@Override public Color getColor() { return color; }
public static void public static void
serializeStaticState(ObjectOutputStream os) serializeStaticState(ObjectOutputStream os)
throws IOException { os.writeObject(color); } throws IOException {
os.writeObject(color);
}
public static void public static void
deserializeStaticState(ObjectInputStream os) deserializeStaticState(ObjectInputStream os)
throws IOException, ClassNotFoundException { throws IOException, ClassNotFoundException {
color = (Color)os.readObject(); color = (Color)os.readObject();
} }
Line(int xVal, int yVal, int dim) {
super(xVal, yVal, dim);
}
@Override public void setColor(Color newColor) {
color = newColor;
}
@Override public Color getColor() { return color; }
} }
public class AStoreCADState { public class AStoreCADState {
public static void main(String[] args) { public static void main(String[] args) {
List<Class<? extends Shape>> shapeTypes = List<Class<? extends Shape>> shapeTypes =
Arrays.asList( Arrays.asList(Circle.class, Line.class);
Circle.class, Square.class, Line.class); List<Shape> shapes = IntStream.range(0, 5)
List<Shape> shapes = IntStream.range(0, 10)
.mapToObj(i -> Shape.randomFactory()) .mapToObj(i -> Shape.randomFactory())
.collect(Collectors.toList()); .collect(Collectors.toList());
// Set all the static colors to GREEN: // Set all the static colors to GREEN:
shapes.forEach(s -> s.setColor(Color.GREEN)); shapes.forEach(s -> s.setColor(Color.GREEN));
// Save the state vector: // Serialize everything to CADState.dat:
try( try(
ObjectOutputStream out = ObjectOutputStream out =
new ObjectOutputStream( new ObjectOutputStream(
@ -106,15 +95,10 @@ public class AStoreCADState {
} }
} }
/* Output: /* Output:
[class CircleColor[GREEN] xPos[58] yPos[55] dim[93] [
, class SquareColor[GREEN] xPos[61] yPos[61] dim[29] class Circle GREEN xPos[58] yPos[55] dim[93],
, class LineColor[GREEN] xPos[68] yPos[0] dim[22] class Line GREEN xPos[61] yPos[61] dim[29],
, class CircleColor[GREEN] xPos[7] yPos[88] dim[28] class Circle GREEN xPos[68] yPos[0] dim[22],
, class SquareColor[GREEN] xPos[51] yPos[89] dim[9] class Line GREEN xPos[7] yPos[88] dim[28],
, class LineColor[GREEN] xPos[78] yPos[98] dim[61] class Circle GREEN xPos[51] yPos[89] dim[9]]
, class CircleColor[GREEN] xPos[20] yPos[58] dim[16]
, class SquareColor[GREEN] xPos[40] yPos[11] dim[22]
, class LineColor[GREEN] xPos[4] yPos[83] dim[6]
, class CircleColor[GREEN] xPos[75] yPos[10] dim[42]
]
*/ */

View File

@ -19,8 +19,7 @@ public class RecoverCADState {
List<Class<? extends Shape>> shapeTypes = List<Class<? extends Shape>> shapeTypes =
(List<Class<? extends Shape>>)in.readObject(); (List<Class<? extends Shape>>)in.readObject();
Line.deserializeStaticState(in); Line.deserializeStaticState(in);
List<Shape> shapes = List<Shape> shapes = (List<Shape>)in.readObject();
(List<Shape>)in.readObject();
System.out.println(shapes); System.out.println(shapes);
} catch(IOException | ClassNotFoundException e) { } catch(IOException | ClassNotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -28,15 +27,10 @@ public class RecoverCADState {
} }
} }
/* Output: /* Output:
[class CircleColor[RED] xPos[58] yPos[55] dim[93] [
, class SquareColor[RED] xPos[61] yPos[61] dim[29] class Circle RED xPos[58] yPos[55] dim[93],
, class LineColor[GREEN] xPos[68] yPos[0] dim[22] class Line GREEN xPos[61] yPos[61] dim[29],
, class CircleColor[RED] xPos[7] yPos[88] dim[28] class Circle RED xPos[68] yPos[0] dim[22],
, class SquareColor[RED] xPos[51] yPos[89] dim[9] class Line GREEN xPos[7] yPos[88] dim[28],
, class LineColor[GREEN] xPos[78] yPos[98] dim[61] class Circle RED xPos[51] yPos[89] dim[9]]
, class CircleColor[RED] xPos[20] yPos[58] dim[16]
, class SquareColor[RED] xPos[40] yPos[11] dim[22]
, class LineColor[GREEN] xPos[4] yPos[83] dim[6]
, class CircleColor[RED] xPos[75] yPos[10] dim[42]
]
*/ */

View File

@ -15,6 +15,5 @@ public class StreamOfRandoms {
} }
} }
/* Output: /* Output:
58 -1 55 93 -1 61 61 29 -1 68 0 22 7 -1 88 28 51 89 9 58 -1 55 93 -1 61 61 29 -1 68 0 22 7 -1 88 28 51 89 9 -1
-1
*/ */

26
strings/BackSlashes.java Normal file
View File

@ -0,0 +1,26 @@
// strings/BackSlashes.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
public class BackSlashes {
public static void main(String[] args) {
String one = "\\";
String two = "\\\\";
String three = "\\\\\\";
System.out.println(one);
System.out.println(two);
System.out.println(three);
System.out.println(one.matches("\\\\"));
System.out.println(two.matches("\\\\\\\\"));
System.out.println(three.matches("\\\\\\\\\\\\"));
}
}
/* Output:
\
\\
\\\
true
true
true
*/

View File

@ -2,13 +2,17 @@
// (c)2021 MindView LLC: see Copyright.txt // (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose. // We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information. // Visit http://OnJava8.com for more book information.
import java.util.stream.*;
public class IntegerMatch { public class IntegerMatch {
public static void main(String[] args) { public static void main(String[] args) {
System.out.println("-1234".matches("-?\\d+")); String possiblyMinus = "-?\\d+";
System.out.println("5678".matches("-?\\d+")); Stream.of(
System.out.println("+911".matches("-?\\d+")); "-1234".matches(possiblyMinus),
System.out.println("+911".matches("(-|\\+)?\\d+")); "5678".matches(possiblyMinus),
"+911".matches(possiblyMinus),
"+911".matches("(-|\\+)?\\d+")
).forEach(System.out::println);
} }
} }
/* Output: /* Output:

View File

@ -4,7 +4,7 @@
// Visit http://OnJava8.com for more book information. // Visit http://OnJava8.com for more book information.
// A very simple version of the "grep" program // A very simple version of the "grep" program
// {java JGrep // {java JGrep
// WhitherStringBuilder.java 'return|for|String'} // WhitherStringBuilder.java "return|for|String"}
import java.util.regex.*; import java.util.regex.*;
import java.nio.file.*; import java.nio.file.*;
import java.util.stream.*; import java.util.stream.*;
@ -18,19 +18,33 @@ public class JGrep {
System.exit(0); System.exit(0);
} }
Pattern p = Pattern.compile(args[1]); Pattern p = Pattern.compile(args[1]);
// Iterate through the lines of the input file:
int index = 0;
Matcher m = p.matcher(""); Matcher m = p.matcher("");
for(String line : // Iterate through the lines of the input file:
Files.readAllLines(Paths.get(args[0]))) { Files.readAllLines(Paths.get(args[0])).forEach(
line -> {
m.reset(line); m.reset(line);
while(m.find()) while(m.find())
System.out.println(index++ + ": " + System.out.println(
m.group() + ": " + m.start()); m.group() + ": " + m.start());
} }
);
} }
} }
/* Output: /* Output:
0: for: 4 String: 18
1: for: 4 String: 20
String: 9
String: 25
String: 4
for: 4
String: 8
return: 4
String: 9
String: 25
String: 4
String: 31
for: 4
String: 8
return: 4
String: 20
*/ */

View File

@ -23,18 +23,3 @@ public class SimpleDebugging {
foo1(); foo1();
} }
} }
/* Output:
In foo1
In foo2
In foo3
___[ Error Output ]___
Exception in thread "main"
java.lang.ArithmeticException: / by zero
at
SimpleDebugging.foo3(SimpleDebugging.java:17)
at
SimpleDebugging.foo2(SimpleDebugging.java:11)
at SimpleDebugging.foo1(SimpleDebugging.java:7)
at
SimpleDebugging.main(SimpleDebugging.java:20)
*/