假设有 3 个类, 他们的继承关系是这样的
public class Person {
}
public class Gril extends Person {
}
public class Boy extends Person {
}
public class Father {
}
在类上指定的泛型, 那么在当前类, 使用的都是这个对象
public class MyTest<T> {
public void println(T t){
System.out.println(t.getClass().getSimpleName());
}
public static void main(String[] args) {
new MyTest<Person>(); // 打印的是 Person
new MyTest<Gril>(); // 打印的是 Gril
}
}
方法上面的泛型
public static <T extends Person> void println1(T t) {
System.out.println(t.getClass().getSimpleName());
}
泛型的上限和下限
<T extends Person> 泛型上限, 只能是 Person 或者是 Person 的子类
<T super Person> 泛型下限, 只能是 Person 或者是 Person 的父类
泛型通配符: 表示可接受一切类型
ArrayList<Boy> arrayList1 = new ArrayList<>();
ArrayList<Gril> arrayList2 = new ArrayList<>();
ArrayList<Person> arrayList3 = new ArrayList<>();
ArrayList<Father> arrayList4 = new ArrayList<>();
println1(arrayList1);
println1(arrayList2);
println1(arrayList3);
println1(arrayList4);
public static void println1(List<?> t) {
System.out.println(t.getClass().getSimpleName());
}
泛型擦除
ArrayList<String> list1 = new ArrayList<String>();
list1.add("abc");
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(123);
// 打印的结果为 true 类型一致, 这就是泛型擦除
System.out.println("类型是否一致 " + (list1.getClass() == list2.getClass()));
这里的结果为什么会为 true 呢? 这就是因为泛型在编译时期就被擦除了, 他们在编译后都是 List 类型相等, 所以为 true, 这个时候如果我们在手写代码的时候, 如果是添加其他的类型仍然会报错, 这个又是为什么呢 ? 这是因为, 其实是在编译之前, 编译器会帮我们检查类型是否是一致的, 避免发生强转失败的现象
最后再看一个现象
ArrayList<? extends Person> arrayList = new ArrayList<>();
arrayList.add(new Person()); // 报错
arrayList.add(new Boy()); // 报错
不能够添加, 这个是为什么 ? 这个因为虽然你使用了通配符接受了继承至 Person 的任意类型, 但是其实编译器并不知道你的 arrayList 是具体的那一个类型的, 所以不能添加, 其实和你写 <? extends Object> 是一样的, 编译器并不能够确定是具体的那一个类型, 那接着只需要简单修改一下, 就不会再报错了
ArrayList<? super Person> arrayList = new ArrayList<>();
arrayList.add(new Person());
arrayList.add(new Boy());
//arrayList.add(new Father()); // 报错, 因为 Father 不是 Person 的子类
这样就不会报错了, 这又是为什么呢 ? 其实当这个时候, 规则是泛型下限, 只能够接受 Person 的父类, 这个时候就能够确定要添加的类型了, 那么也就意味着, arrayList 添加子类是肯定没有问题的, 只要父类出现的地方, 子类一定能够出现, 这也遵循了一大原则: 里氏替换原则
- 原文作者: midFang
- 原文链接: https://midFang.github.io/post/java-%E4%B8%AD%E7%9A%84%E6%B3%9B%E5%9E%8B.html
- 版权声明:本作品采用 署名-非商业性使用 4.0 国际 (CC BY-NC 4.0)进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。