[Effective Java 3rd Edition](https://www.amazon.co.jp/Effective-Java-%E7%AC%AC3%E7%89%88-%E3%], which is a must-have book for intermediate Java users and above. 82% B8% E3% 83% A7% E3% 82% B7% E3% 83% A5% E3% 82% A2% E3% 83% BB% E3% 83% 96% E3% 83% AD% E3% 83% 83% E3% 82% AF-ebook / dp / B07RHX1K53) has a Kindle version, so I will summarize it.
Previous: Effective Java 3rd Edition Chapter 4 Classes and Interfaces Next: Effective Java 3rd Edition Chapter 6 enums and annotations
--Parameterized type ... List <String>
--Actual parameter ・ ・ ・ String
--Generic type ・ ・ ・ List <E>
--Temporary parameter ・ ・ ・ ʻE --Non-boundary wildcard type ...
List <?> --Original form ...
List --Boundary parameter ・ ・ ・ <ʻE extends Number>
--Recursive boundary ・ ・ ・ <T extends Comparable <T >>
--Boundary wildcard type ・ ・ ・ List <? Extends Number>
--Generic method ・ ・ ・ static <E> List <E> asList (E [] a)
--Type token ・ ・ ・ String.class
--Do not use the prototype, which is a generic type with no type parameters. (List
etc. without<>
)
--It's okay to use List <Object>
. You can pass List <String>
to List
(prototype), but it is safe because you cannot pass it toList <Object>
.
--Set <Object>
is a parameter type (safe) that represents a Set that can contain objects of any type.
--Set <?>
Is a wildcard type (safe) that represents a Set that can contain objects of some unknown type.
Prototype example
// NG
private final Collection stamps = ... ;
// OK
private final Collection<Stamp> stamps = ... ;
// NG
static int numElementsInCommon(Set s1, Set s2) { ... }
// OK
static int numElementsInCommon(Set<?> s1, Set<?> s2) { ... }
--All unchecked warnings indicate the possibility of a ClassCastException
at runtime.
--If you cannot remove the unchecked warning, suppress the warning with the @SuppressWarnings ("unchecked")
annotation and leave the reason in the comment.
@SuppressWarnings("unchecked")Suppress annotation warnings
public <T> T[] toArray(T[] a) {
if (a.length < size) {
// T[]This cast is correct because it produces an array of the same type that was passed as
@SuppressWarnings("unchecked") T[] result = (T[]) Arrays.copyOf(elementData, size, a.getClass());
return result;
}
System.arraycopy(elements, 0,va, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
--The sequence is defective and does not fit well with the generics. None of new List <E> []
, new List <String> []
, and new E []
are allowed.
--Arrays do not provide compile-time type safety, but generics are type safe.
Generics unused
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
this.elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; //★ Remove obsolete references
return result;
}
public boolean isEmpty() {
return size == 0;
}
private void ensureCapacity() {
if (elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
--Change ʻObject to ʻE
.
Example of rewriting to generics
public class Stack<E> {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
@SuppressWarnings("unchecked") //Suppress warnings
public Stack() {
// new E[]Can't, so Object[]E[]Cast to (no inspection warning appears)
this.elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(E e) {
ensureCapacity();
elements[size++] = e;
}
public E pop() {
if (size == 0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null; //★ Remove obsolete references
return result;
}
public boolean isEmpty() {
return size == 0;
}
private void ensureCapacity() {
if (elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
--The list of type parameters for generic methods that declare type parameters <E>
falls between the method qualifier and the return type of the method.
--You can be more flexible by using the boundary wildcard type.
Generic method
public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
Set<E> result = new HashSet<>(s1);
result.addAll(s2);
return result;
}
Example using border wildcards
//Wildcard type for parameters as an E-producer
public void pushAll(Iterable<? extends E> src) {
for (E e : src) {
push(e);
}
}
//Wildcard type for parameters as an E-consumer
public void popAll(Collection<? super E> dat) {
while (!isEmpty()) {
dat.add(pop());
}
}
--Do not use boundary wildcard type as return type.
public static <E> Set<E> union(Set<? extends E> e1, Set<? extends E> e2)
--Variadic methods and generics were added at the same time in Java 5, but they don't work together.
--Heap pollution occurs when a variable of a parameterized type references an object that is not of that type.
--It is not safe to store values in generic variable length array parameters.
--Generic variable length parameters are not type safe but allowed.
--If you write a method with generic variable length parameters, first make the method type safe. Annotate with @SafeVarags
for ease of use.
--A container that stores a key as a Class and a value as an instance on a map.
Type-safe heterogeneous container pattern
public class Favorites {
private Map<Class<?>, Object> favorites = new HashMap<>();
public <T> void putFavorite(Class<T> type, T instance) {
favorites.put(Objects.requireNonNull(type), instance);
}
public <T> T getFavorite(Class<T> type) {
return type.cast(favorites.get(type));
}
}
//Call example
Favorites f = new Favorites();
f.putFavorite(String.class, "Java");
f.putFavorite(Integer.class, 0xcafebabe);
f.putFavorite(Class.class, Favorites.class);
String favoriteString = f.getFavorite(String.class);
int favoriteInteger = f.getFavorite(Integer.class);
Class<?> favoriteClass = f.getFavorite(Class.class);
Recommended Posts