什么是类型擦除?

  Java   8分钟   593浏览   0评论
  • 泛型是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());
        } 
      } 
}
  1. 类型擦除后,两个属性的类型都是为 Object类型。

  2. 在泛型类被类型擦除的时候,之前泛型类中的类型参数如果没有指定上限,如 则会被转成普通的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 条评论