泛型是JDK1.5引进的。
泛型信息只存在编译阶段,在进入JVM之前,与泛型相关的信息会被擦除。通俗来讲,泛型类和普通类在java虚拟机内没有什么特别的地方。
举例1:说明类型擦除
public class TestMessage{
public static void main(String[] args) {
Message<String> message = new Message<>();
Message<Integer> message1 = new Message<>();
System.out.println(message.getClass() == message1.getClass()); //true
System.out.println(message.getClass().getName()); //www.csdn.point.Message
System.out.println(message1.getClass().getName()); //www.csdn.point.Message
}
}
class Message<T> {
private T message;
public void setMessage(T message){
this.message = message;
}
public T getMessage(){
return this.message;
}
@Override
public String toString() {
return "TestMessage{" +
"message=" + message +
'}';
}
}
以上结果中表明他们两个的类型都一致,类型擦除后都是Message 。
举例2:类型擦除后,查看字段信息
//当使用泛型类时,决定属性的具体类型
public class Point2<T> {
private T x;
private T y;
public void setX(T x) {
this.x = x;
}
public T getX(){
return x;
}
public void setY(T y) {
this.y = y;
}
public T getY() {
return y;
}
@Override
public String toString() {
return "Point2{" +
"x=" + x +
", y=" + y +
'}';
}
public static void main(String[] args) {
Point2<Integer> p2 = new Point2<>();
//两个属性
Field[] fields = p2.getClass().getDeclaredFields();
for (Field field:fields){
System.out.println(field.getType().getName());
}
}
}
类型擦除后,两个属性的类型都是为 Object类型。
在泛型类被类型擦除的时候,之前泛型类中的类型参数如果没有指定上限,如
则会被转成普通的Object类型,如果指定了上限如 ,则类型参数就会被替换成类型上限。
举例:有上限类型
public class Point6 <T extends CharSequence>{
private T x;
private T y;
public void setX(T x) {
this.x = x;
}
public T getX(){
return this.x;
}
public void setY(T y) {
this.y = y;
}
public T getY() {
return this.y;
}
@Override
public String toString() {
return "Point6{" +
"x=" + x +
", y=" + y +
'}';
}
public static void main(String[] args) {
Point6<String> p1 = new Point6<>();
//两个属性
Field[] fields = p1.getClass().getDeclaredFields();
for (Field field:fields){
System.out.println(field.getType().getName()); //java.lang.CharSequence
}
}
}
以上结果中,两个属性x, y 的类型都是CharSequence。
end:
Java泛型是伪泛型,因为Java在编译期间,所有的泛型信息都会被擦除掉,这就是通常所说的类型擦除。
以下举例说明:
可以看到如果直接在Integer类型集合中添加字符串是会报错的,那么是不是就一定不能添加了呢?答案是否定的,可以通过Java泛型中的类型擦除特点及反射机制实现。
反射实现类型擦除
代码如下
package demo;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* @author: 邹祥发
* @date: 2021/9/17 10:49
*/
public class Demo02 {
public static void main(String[] args) throws Exception{
ArrayList<Integer> list = new ArrayList<>();
list.add(77);
//反射机制实现
Class<? extends ArrayList> clazz = list.getClass();
Method add = clazz.getDeclaredMethod("add", Object.class);
add.invoke(list,"zou");
System.out.println(list);
}
}
运行结果
[77, zou]

评论区 0