package JavaTest;
import java.util.ArrayList;
/**
* Create by zgn on 2022/2/8 12:12
**/
//TODO 泛型擦除测试
public class genericTypeEraser {
public static void main1(String[] args) {
ArrayList arrayList = new ArrayList();
ArrayList<String> list = new ArrayList<>();
// list.add(1) 编译的时候就会报错
arrayList.add("abc");
arrayList.add(2);
for (int i = 0; i < arrayList.size(); i++) {
String item = (String) arrayList.get(i);
System.out.println(item);
}//运行时报错 java.lang.ClassCastException:
// java.lang.Integer cannot be cast to java.lang.String
/*TODO list以第一次添加的数据类型为准 即以String的方式使用 后面再添加Integer类型的数据
* 程序就崩溃了
* 为了在编译的时候解决类似的问题 我们可以在代码中指定泛型的类型*/
}
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
ArrayList<Integer> list1 = new ArrayList<>();
Class<? extends ArrayList> aClass = list.getClass();
Class<? extends ArrayList> aClass1 = list1.getClass();
System.out.println(aClass.getName());
System.out.println(aClass == aClass1);//返回结果为true
/*TODO 该例子可以证明,编译之后程序会采取去泛型化的措施,也就是Java中的泛型,只在编译的阶段有效
* 在编译的过程中,正确检查泛型结果后,在运行的时候将泛型的相关信息擦除
* 编译器只会在对象进入JVM和离开JVM的边界处添加类型检查和转换的方法,泛型信息不会进入到运行时的阶段
* 这就是Java的泛型擦除 泛型擦除有两种方式 java使用的是第一种方式 C++和C#使用的是第二种方式
* 1)Code sharing。对同一个原始类型下的泛型类型 只生成同一根目标代码 假泛型
* 2) Code specialization 对每一个泛型类型都生成不同的目标代码 真泛型
* 程序在运行的时候对泛型类型没有感知 所以上述例子的代码反编译之后只剩下了list 实际上都是
* Class<? extends ArrayList>的比较 导致上面的例子中输出的结果为true
* TODO Java 采用Code sharing机制进行类型擦除的原因:
* 1)Java泛型是1.5才出现的特性 在此之前JVM已经在无泛型的条件下经历了较长时间的发展,如果采用
* Code specialization 就要对JVM的类型系统做伤筋动骨的改动 并且无法保证向前的兼容性
* 2)Code specialization对每个泛型类型都生成不同的目标代码,如果有10个不同泛型的list 就要生成
* 10份字节码 造成代码膨胀*/
}
}
类型擦除对Flink的影响
public class genericTypeForFlink {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
// Returns a fixed-size list backed by the specified array.
env.fromCollection(Arrays.asList("hello", "world", "java", "scala"))
.map(w -> Tuple2.of(w, 1)).print();
/*Caused by: org.apache.flink.api.common.functions.InvalidTypesException: The generic type
parameters of 'Tuple2' are missing. In many cases lambda methods don't provide enough information
for automatic type extraction when Java generics are involved. An easy workaround is to use an
(anonymous) class instead that implements the 'org.apache.flink.api.common.functions.MapFunction'
interface. Otherwise the type has to be specified explicitly using type information.*/
env.execute();
}
}