符号说明:<=>表示等价于 //!表示注释的代码是错误的
1 不可创建泛型数组
//! Object o = new List<String>[10];
//! Object o = new E[10];
//! Object o = new List<E>[10];
// 上面3行代码是错误的
2 数组是协变的,int 不是Object的子类,所以int[]不是Object[]的子类型,但Integer[]是Object[]的子类型,即Integer[]类型变量可以赋值给Object[]
3 可变参数可以用数组赋值或多个参数赋值;而数组参数只能用数组赋值
public void varargs(int[] arg) {
}
public void callVarargs() {
//! varargs(1, 3);
varargs(new int[] {3, 3});
}
4 可以声明泛型数组但不可以创建泛型数组,可以把泛型数组作为函数的参数(不会产生警告)或使用泛型可变参数(会有potential heap pollution警告,用@SafeVarargs已知警告)
5 泛型单例工厂,需要类型兼容即
package com.ape.effectivejava;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
/**
* Hello world!
*
*/
public class App<E>
{
private static final UnaryFunction<Object> IDENTITY_FUCNTION = new UnaryFunction<Object>() {
@Override
public Object apply(Object arg) {
return arg;
}
};
private static final UnaryFunction<App<String>> APP_FUNCTION = new UnaryFunction<App<String>>() {
@Override
public App<String> apply(App<String> arg) {
return arg;
}
};
public static <T> UnaryFunction<T> identityFunction() {
return (UnaryFunction<T>) IDENTITY_FUCNTION;
}
public static <T> UnaryFunction<T> appFunction() {
return (UnaryFunction<T>) APP_FUNCTION;
}
public static void main( String[] args )
{
System.out.println("Hello World!" );
UnaryFunction<String> sm = identityFunction();
System.out.println("string test: " + sm.apply("ff"));
UnaryFunction<Integer> im = identityFunction();
UnaryFunction<String> appByte = appFunction();
appByte.apply("ff"); //!这里会报错,因为类型不兼容String与App<String>
new HashSet();
App x = new App();
if (x instanceof Object) {
System.out.println("xx");
}
App[] arx = new App[10];
Object[] oarx = arx;
// ArrayList<String>[] fi = {new ArrayList()};
if (arx instanceof Object[]) {
}
App argx = new App();
argx.varargs(new int[]{3, 5});
new ArrayList<String>().toArray();
Class<?> cc = App[].class;
System.out.println("equals: " + (arx.getClass() == cc) + "");
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<Integer> list2 = new ArrayList<Integer>();
reduce(list1, null, "");
reduce(list2, null, 1);
}
@SafeVarargs
//避免使用泛型可变参数
public final void genericVariable(List<String>... args) {
}
public void varargs(int... arg) {
Object o = new int[10];
}
public static <T> T reduce(ArrayList<T> list, Function<T> f1, T init) {
T[] es = null;
es = (T[]) list.toArray();
System.out.println("class type: " + init.getClass() + (init.getClass() == String.class) );
T r = init;
for (T e : es) {
if (f1 != null) {
r = f1.apply(r, e);
}
}
return r;
}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
T[] copy = (newType == (Object) Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
}
interface Function<E> {
E apply(E e1, E e2);
}
interface UnaryFunction<T> {
T apply(T arg);
}
6 深刻理解泛型中类型擦除的含义:
private static final UnaryFunction<App<String>> APP_FUNCTION = new UnaryFunction<App<String>>() {
@Override
public App<String> apply(App<String> arg) {
return arg;
}
};
public static <T> UnaryFunction<T> identityFunction() {
return (UnaryFunction<T>) APP_FUNCTION;
}
或者代码如下
private static final UnaryFunction<Object> IDENTITY_FUCNTION = new UnaryFunction<Object>() {
@Override
public Object apply(Object arg) {
return arg;
}
};
public static <T> UnaryFunction<T> identityFunction() {
return (UnaryFunction<T>) IDENTITY_FUCNTION;
}
//使用方法
public static void test() {
UnaryFunction<String> idString = identityFunction();
idString.apply("xx");
}
//类型擦除补充
6.1 声明的类型是什么类型,类型推断时就是什么类型; A b = new B(); putFavorite(b, B.class); 推断出的泛型为A //public static <T> void putFavorite(T instance, Class<T> type)
6.2 原始类型和泛型之间可以互相赋值 List<String> <= List 或 List <= List<String> 泛型之间List<?> <= List<String>, List<String> !<= List<?>
6.3 假定HashSet<Double>.class,HashSet<String>.class存在,那么就有HashSet<Double>.class == HashSet.class == HashSet<String>.class == new HashSet<Double>().getClass(); 要点:所有HashSet<E>泛型的类对象对应同一个List.class
6.4 代码片段
package com.ape.effectivejava;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class GenericJava {
public static void main(String[] args) {
// testSet();
typeInference();
restrictIntegerString();
rawHole();
//!getFavorite(Integer.class);
}
/**
* 把Integer对象放入HashSet
!!!
*/
public static void testSet() {
HashSet hashSet = new HashSet
();
hashSet.add("string");
HashSet
intSet = hashSet;
intSet.add(new Integer(12));
System.out.println("intSet has: " + intSet); //intSet has: [string, 12]
}
private static Map
, Object> favorites = new HashMap
, Object>(); public static
void putFavorite(T instance, Class
type) { favorites.put(type, instance); } public static
T getFavorite(Class
type) { return type.cast(favorites.get(type)); } public static
void putFavorite2(T instance, F type) { } /** * 原生态漏洞,String实例和Integer类型对应,违背设计原则并且getFavorite会抛异常 */ public static void rawHole() { Class integer = Integer.class; Class
f = integer; Class g = f; String xx = ""; putFavorite(xx, integer); // } public static void typeInference() { B b = new B(); Object a = b; CharSequence cs = new String(""); A aa = b; // putFavorite((HashSet
) a, HashSet.class); putFavorite2(aa, cs); //! putFavorite(aa, B.class); //需要HashSet
类型和HashSet
实例,结果传入HashSet
和HashSet
实例 HashSet
hashInteger = new HashSet
(); Class hashClass = new HashSet
().getClass(); Class
cL = List.class; System.out.println("HashSet
.class == " + (HashSet.class == hashClass)); HashSet
xhi = (HashSet
) hashClass.cast(hashInteger); HashSet h = hashInteger; HashSet
xhfi = h; putFavorite(hashInteger, hashClass); } public static void restrictIntegerString() { List
hi = Collections.checkedList(new ArrayList
(), Integer.class); List rawList = hi; List
stringList = rawList; stringList.add("fff"); } public static void testAnnotatedElement(AnnotatedElement element) { Class
c = GenericJava.class; Class
extendClass = (Class
) c; Annotation x = element.getAnnotation(extendClass); } } class A { } class B extends A { }
Set<Integer> set5 = new HashSet<Integer>();
Set<Double> set6 = new HashSet<Double>();
Set<Number> f3f = App.<Number>union2(set5, set6);
8 无限制类型参数可以和无限制通配符相互替换,有限制类型参数可以和有限制通配符相互替换;有限制类型参数表示法
public static <T> void put(Set<T> set) {
}
public static void put2(Set<?> set1) {
}
public static <T extends GenericTest> void putSet(Set<T> xx) {
}
public static void putSet2(Set<? extends GenericTest> xx) {
}
//正确代码
public static <T extends Object> T getSet(Set<T> xx) {
return null;
}
//下面代码错误
public static <T> T getSet(Set<T extends Object> xx) {
return null;
}