java泛型的解释

看视频的时候曾经看到过说java的泛型只是模拟出来的,只在编译阶段有效。对此很不理解,后来经过摸索发现了一点规律:

定义了泛型的限定之后,编译器会在编译阶段对实现了参数化的类型实例进行检查,例如:

ArrayList al=new ArrayList();
al.add(10);

这样在编译阶段他就会将这个错误检查出来,告诉你add()中的参数应该是String类型的。

后来碰到问题如何向参数化类型为String的集合中添加其他类型的数据。然后是用反射解决的:

al.getClass().getMethod("add",Object.class).invoke(al,10);

这样就可以向刚刚那个参数化类型String的集合中添加Integer型的数据了。

通过这个例子可以发现al这个对象他所对应的在内存中的加载的类型依然是ArrayLIst.class。

这个我进行了一下验证发现是的:

System.out.println(al.getClass()==ArrayList.class);

输出结果是true,也就是说声明的参数化类型为String的类型在内存中跟原始类型是同一个。

Integer i=al.get(0);

但是像上面的代码提取的时候会发现这个问题,他会在编译阶段就告诉你al.get(0),返回的是一个String。哪怕我们知道它里面装的是一个Integer,

但是通过前面的参数化类型的声明,编译器就认定了他存进去的是个String,所以返回的也是一个String,所以不能用Integer类型的变量去接受。

String str=al.get(0);
System.out.println(str);
这样用一个String类型的变量去接受了他然后将他打印出来,依然碰到问题,它报告异常:无法从Integer转换到String。这是因为str是一个String类型,打印的时候调用它的toString()方法,但是这个对象却是一个Integer的对象,他无法调用String的toString()方法。所以他JVM会将他强制转换成一个String的对象,但是他们之间没有继承关系,所以出现转换异常。所以由上我们可以直到,泛型限定的只是在编译阶段,只要能通过编译,在运行时候的内存中,我们可以将那个参数化类型当作Object来看待。


你可能感兴趣的:(java语言基础)