Java泛型

什么是泛型

Java泛型(generics) 是JDK5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型泛型的本质是参数类型,也就是说所操作的数据类被指定为一个参数泛型不存在于JVM虚拟机

泛型的好处

泛型可以增强编译时错误检测,减少因类型问题引发的运行时异常泛型具有更强的类型检查
泛型可以避免类型转换
分型可以泛型算法,增加代码复用性

泛型的类型

  • 泛型类

    public class Test1 {}
    
  • 泛型接口

    public interface Test1 {}
    
  • 泛型方法

    public  void a(T t) {}
    
    public void test(List list){}//这不是泛型方法
    

PECS法则

List 非限定通配符 是一个泛型类型 ? 位置 等价于 List
List List 统称为限定通配符

非限定通配符不能写也不能读 但也有好处,编译还是会进行类型安全检查

  • extends :上界只取不存 消费者
1587695546146.png

可以发现 通过调用add 方法无法添加,但是可以通过反射的方式添加数据
但是取出来的时候可以发现如果不强转的话会报错,但是运行期还是原本的类型

  • super:下界只存不取
    1587695807772.png

可以发现 用过get方法取的时候是Object 而不是Apple 但是实际类型是Apple,Kotlin称之为逆变,java没有这种说法

协变

A的父类是B

A[] 就是 B[]的协变

例子:

public static  void copy(List dest, List src){}//左边是只存不取,右边只取不存

泛型擦除

由于泛型是JDK5引入的 为了做到向下兼容 所有JVM里面是不存在泛型的,代码里写的泛型,在编译期的时候会转换成具体的类型,如果没有就会被擦除,变成Object

1587696376335.png

可以看出 setT方法在.class文件的时候还是T 但是到了字节码文件就变成了Object

泛型的副作用

  • 泛型不行是 基本数据类型 必须是包装类
  • 不能使用 instanceof 运算符(擦除类型丢失)
  • 类的泛型不能再静态方法中使用 (加载顺序不一样,静态先加载的,类是实例加载的,所以静态方法无法获取类的泛型)

其他

1587699455390.png

这种形式的写法 没有任何用处 编译期会给T打一个标识 和LinearLayout没什么关系只认ViewGroup 所以要强转, 甚至我可以给这个泛型RelateLayout类型这样明显就不是LinearLayout了 所以说,jvm并不知道具体是什么类

最后

1587699917390.png

Plate 没有写泛型,编译期不会进行类型检查
Plate 会编译成Object类型 算是没有泛型
Plate 编译会进行类型检查
Plate 编译泛型会被擦除变成Object
Plate 上界 可取不可存 但是可以通过反射进行存储
Plate 下界 可存不可取 取出的类型是Object 需要进行强转

你可能感兴趣的:(Java泛型)