Java 泛型个人总结,发出来共享,以及寻求理论支持

2022-06-14 10:00:28 +08:00
 nothingistrue

泛型基本原理

略,只需注意 Java 泛型是编译擦除机制,只在编译时有效,运行时无效。

泛型标记的区分

完全个人总结,征求来源认证

泛型说到本质,是模板替换,需遵循模板替换的基本原则,需要涉及到下述三种标记。

泛型参数(模板变量)

标记替换什么,即替换内容的含义是什么。这是额外的独立定义,在 Javadoc 会有单独位置,只有类和方法旁边才能定义泛型参数。

举例:

public interface List<E></font> { … } // List 后面的<E>
<T> T[] toArray(T[] a) {} // 最前面的<T>

注意点: 这是个参数声明,因此请勿使用“ ?”。

泛型(模板变量的引用)

标记在哪里替换。这是定义要替换的位置,因此它必定是替换掉之前的位置。类当中的类型声明,例如方法的形参类型,方法返回类型,可被替换为泛型。变量的类型声明,不属于类,故不参与泛型,而是参与后文所述的定型。

举例:

public interface List<E> { boolean add(E e); } // add 方法的参数类型 E
 <T> T[] toArray(T[] a) {} // 参数类型 T , 还有 返回类型 T[]

注意点: Class<T> { List<T> getList(List<T> paramList); } ,两个 List<T> 中这个 T , 在 Class 类中是泛型 ,但同时,也是对 List<E> 的 泛型参数 E 的定型。

定型(模板变量的值)

标记替换成什么。_模板变量的值可能无需刻意定义,只要能根据上下文推断出来即可_

举例:

List<String> = new ArrayList<String>() // 显式定义
Optional.of("123").orElseGet(()->"sss"); // 上下文自动推断
List<String> = new ArrayList<>(); // 显式定义+上下文自动推断
List<? extends B> bList= new ArrayList<A>; // 向上造型通配符
List<? super A>   bList = new AyyarList<B>; // 向下造型通配符

关于造型通配符,见后文

extends/super 特别说明

__ <? extends SomeObject>,跟 <T extend SomeObject>,是两码事: __

关于造型通配符,见后文

造型通配符

特别说明: Java 泛型是 1.5 加入,并且加入之后再没有动过,这里的笔记也是 Java 6 年代总结的,那时候 C# 泛型可能还没出或者出来了但没流行。所以这里没有 PECS ,没有斜变逆变,这俩理论可以作为外部参考,但是它们不太可能是 Java 泛型的基础原理。

由于类型参数与类型声明无关,因此类型参数的继承关系不能区分泛型实例的继承关系。例如List<Integer>List<Object>之间没有继承关系,他们都是 List 接口的实例并且由于加入了类型参数限定二者之间也不能做强制类型转换。而自然情况以及面向对象的多态型又是需要该区分的即List<Integer>List<Object>的子类,此时需要使用“? extends”、“? super”通配符,但是注意这只是一种变通手段,并且是不完善的。毕竟泛型是 编译时 的特征,而多态是 运行时 的特征。

提示: 下文均假设 A extends B 。

向上造型通配符

** 可以使用其“方法返回类型限定”的方法(例如 get 方法),不能使用其“方法参数类型限定”的方法(例如 add 、set 方法)。 **

举例:

List< ? extends B> bList= new AyyarList<A>;
B b = bList.get(0); // 正确
bList.add(new A()); // 编译错误 

分析:

向下造型通配符

可以使用其“方法参数类型限定”的方法(例如 add 、set 方法),不过参数类型应当是类型参数或其子类型(而不是父类);仍然可以使用其“方法返回类型限定”的方法(例如 get 方法),但只能得到 Object 类型的返回类型。

举例:

List<? super A> bList = new AyyarList<B>;
bList.add(new A()); // 正确
bList.add(new B()); // 编译警告,但不是编译错误,
Object obj = bList.get(0); // 可用,但是没有实际意义

分析:

造型通配使用原则

2036 次点击
所在节点    Java
3 条回复
nothingistrue
2022-06-14 10:09:57 +08:00
联动 /t/859220 /t/858692 ,那里面我的回复不用看了,中间过程的回复,有不少错误。
fredli
2022-06-14 10:26:52 +08:00
明白类型擦除,很多都理解了啊
siweipancc
2022-06-14 11:13:48 +08:00
我是看 oracle 教程的,简单明了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/859452

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX