泛型是一种"代码模板"
T
可以是任何class
. 编写一次模板, 创建任意类型的ArrayList
ArrayList<T>
, 然后再代码中为用到的类创建ArrayList<类型>
ArrayList<T> implements List<T>
: ArrayList<T>
向上转型为List<T>
ArrayList<Integer>
和ArrayList<Number>两者完全没有继承关系
Object
.Object
没有发挥泛型的优势.List<Number> list = new ArrayList<>;
<T>
, 然后在这个类里面就有了这么一种类型T
, 任意使用<T>不能用于静态方法
public class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() {
return first;
}
public T getLast() {
return last;
}
// 对于静态方法使用<T>
public static<K> Pair<K> create(K first, K last) {
return new Pair<K>(first, last);
}
}
<T, K>
Pair<String, Integer>
T
视为Object
处理.T
的类型, 自动为我们实行安全地强制类型.<T>
不能是基本类型, 例如int
, 因为实际类型是Object
.Class
: <T>
是Object
, 无论T
的类型是什么, getClass()
返回同一个Class
实例Class
: 不存在Pair<String>.class
, 只存在唯一的Pair.class
T
类型: 只能通过反射传入实现.equals(T t)
不会覆写成功, 因为摩擦成equals(Object t)
, 这就是一个覆写方法了class IntPair extends Pair<Integer> {
public IntPair(Integer first, Integer last) {
super(first, last);
}
}
public class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
}
// 可以直接使用: Integer ip = new IntPair(1, 2)
// 获取继承泛型类型方法
Class<IntPair> clazz = IntPair.class;
Type t = clazz.getGenericSuperclass();
if (t instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) t;
Type[] types = pt.getActualTypeArguments();
Type firstType = types[0];
Class<?> typeClass = (Class<?>) firstType;
System.out.println(typeClass);
}
Class
来标识泛型不够用. 所以: java类型的体系如下:Pair<Integer>
类型, 符合参数Pair<? extends Number>
: 上界通配符, 类型T上界限定在Number
setFirst(? extends Number)
无法传递任何Number
类型给setFirst(? extends Number)
null
, // ok, 但是后面排除NullPointerException
get
获取一个指定类型的返回结果set
进行设置和修改类型extends
通配符表示可以读, 不能写.Pair<T>
的时候, 可以使用extends
通配符来限定T
的类型set(? super Integer)
传入Integer
的引用get()
方法获得Integer
的引用<? super Integer>
通配符作为方法参数, 便是方法内部代码对于参数只能写, 不能读extends
和super
通配符<? extends T>
允许调用方法T get()
获取T
的引用, 但不允许调用方法set(T)
传入T
的引用(传入null
除外)<? super T>
允许调用方法set(T)
传入T
的引用, 但不允许调用方法T get()
获取T
的引用(获取Object
除外)class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
// 编辑器可以避免: 意外读取dest, 意外操作src. 安全操作数组
for (int i = 0; i < src.size(); i++) {
T t = src.get(i);
dest.add(t);
}
}
}
T
, 它是生产者(Producer), 需要使用extends
通配符T
, 它是消费者(Consumer), 需要使用super
通配符T
的src
是生产者, 声明为<? extends T>
T
的dest
是消费者, 声明为<? super T>
?
void sample(Pair<?> p) {}
<?>
具体作用:
set<T>
方法传入引用T
(null
除外)T get<>
方法并获取T
引用(只能获取Object
引用)null
判断null
判断, 大多数情况下, 引入泛型参数<T>消除<?>通配符
Pair<?>是所有的Pair<T>
的超类Pair<Integer> p = new Pair<>(123, 456);
Pair<?> p2 = p; // 安全的向上转型
Class<T>
就是泛型Class
的getSuperclass()
方法返回的Class
类型是Class<? super T>
Constructor<T>
也是泛型Class<Integer> clazz = Integer.class;
Constructor<Integer> cons = clazz.getConstructor(int.class);
Integer i = cons.newInstance(123);
new
操作符创建, 必须通过强制转型实现.// Pair<String>[] ps = null; // ok
// Pair<String>[] ps = new Pair<String>[2]; // Cannot create a generic array of Pair<String>
Pair<String>[] ps = (Pair<String> []) new Pair[2];
class ABC<T> {
// T[] createArray() {
// return new T[5];
// }
T[] createArray(Class<T> cls) { // 借助`Class<T>创建泛型数组`
return (T[]) Array.newInstance(cls, 5);
}
}
int
和Integer
两种类型的关系和区别?原文:https://www.cnblogs.com/zhangrunhao/p/12655285.html