package tryAny.effectiveJava;
public class GenericsTest5 {
public static void main(String[] args) {
Object[] objAry = new Long[1];
objAry[0] = "aa";
// Won't compile!
// List<Object> ol = new ArrayList<Long>(); // Incompatible
}
}
Arrays are reified. Arrays know the elements at run time and process the elements. Generics, on the other hand, are implemented by erasures. Generics are type-restricted only at compile time, and element type information is discarded at run time.
Due to the fundamental differences mentioned above, sequences and generics cannot be mixed well. For example, code such as ``` new List
// Why generic array creation is illegal - won't compile!
List<String>[] stringLists = new List<String>[1]; // (1)
List<Integer> intList = List.of(42); // (2)
Object[] objects = stringLists; // (3)
objects[0] = intList; // (4)
String s = stringLists[0].get(0); // (5)
Types such as * E and List
SafeVarargs
annotation (Item32).package tryAny.effectiveJava;
import java.util.Collection;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class Chooser1 {
private final Object[] choiceArray;
public Chooser1(Collection choices) {
choiceArray = choices.toArray();
}
public Object choose() {
Random rnd = ThreadLocalRandom.current();
return choiceArray[rnd.nextInt(choiceArray.length)];
}
}
According to Item29, I wrote the following in Generics. It's a bit verbose and performance degradation, but it doesn't throw a ClassCastException at runtime.
package tryAny.effectiveJava;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
//List-based Chooser - typesafe
public class Chooser2<T> {
private final List<T> choiceList;
public Chooser2(Collection<T> choices) {
choiceList = new ArrayList<>(choices);
}
public T choose() {
Random rnd = ThreadLocalRandom.current();
return choiceList.get(rnd.nextInt(choiceList.size()));
}
}
Recommended Posts