java语法糖--泛型与类型擦除

参考来源:《深入理解Java虚拟机》 周志明 著
语法糖:
也被称为“糖衣语法”,是指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员的使用,然而虚拟机在运行时却是不支持这种语法,所以它们将会在编译期间就会被解语法糖,也就是还原回简单的基础语法结构。

在java中常用的语法糖主要有:泛型(不过泛型不一定都是语法糖实现,如C#,而是直接由CLR支持的)、变长参数、自动装箱/拆箱。

泛型是JDK1.5的一项新增特性,本质在于参数化类型的应用,可以说是操作的数据类型被指定为一个参数,且这种参数可以用于类、接口、方法中。
在泛型没有出现之前,java都是通过Object类来进行强制转换从而实现类型的泛化,由于这个Object类是java所有类型的父类,所以这个Object是可以转换成任何对象的,那么在这里就会很容易产生比较大的风险。
比较一下C#和java对泛型技术的使用:
C#里面尽管仿佛是和java一样相似的使用方式,但它们之间的实现方式是有着根本的分歧的。
C#里面的泛型无论是在程序源码、编译后的IL中(Intermediate Language,中间语言,这时候泛型就是一个占位符)、运行期的CLR中都是切实存在的,比如List<int>和List<String>就是两个不同的类型,在系统运行期生成,它们有着的自己的虚方法和类型数据,这种实现被称为类型膨胀,基于这种方法的泛型就被称为真实泛型
然而,java中它只存在与程序的源码之中,在编译后的字节码文件中,就已经被替换为原来的原生类型,也就是裸类型,所以对于运行期的Java语言来说,ArrayList<int>ArrayList<String>就是同一个类,因此该泛型技术才被称作语法糖,java语言的泛型实现方法称之为类型擦除,基于这种实现方法称为伪泛型
那么举个栗子呗(鉴于笔者并未接触过C#,故此只会写Java的栗子):
这是一个简单的栗子

 public static void main(String[] args) {
        Map<String,String> map = new HashMap<String,String>();
        map.put("hello","你好");
        map.put("how are you","吃了吗");
        System.out.println(map.get("hello"));
        System.out.println(map.get("how are you"));
    }

看看其class文件的转换代码,很明显泛型类型就被转换为原生类型

 public static void main(String[] args) {
        Map<String, String> map = new HashMap();
        map.put("hello", "你好");
        map.put("how are you", "吃了吗");
        System.out.println((String)map.get("hello"));
        System.out.println((String)map.get("how are you"));
    }

那么我们再看一个我自己写的一个例子吧

public class Test<T> {
    T a;

    public T getA() {
        return a;
    }

    public void setA(T a) {
        this.a = a;
    }
    public static void main(String[] args) {
        Test<Integer> test = new Test<>();
        test.setA(12);
        System.out.println(test.getA());
        System.out.println(test.getClass());
    }
}

本来想通过idea的反编译插件来看反编译结果呢,但是它给我显示的是这个结果,让我一度郁闷,咋就没擦除呢,难道是官方说错了吗,别急,这里只不过是现在的反编译工具比较智能而已,直接给你显示和原来的一样。
在这里插入图片描述
让我们看看通过命令行工具来查看javap -c
在这里插入图片描述
虽然我不懂这个字节码指令,但是我们可以通过旁边的注释来了解,明显类型都是被擦除了,所以按照之前的理解是正确的。

当然当我们对方法进行重载的时候,就会出现一些问题,也就是无法重载(也就是上文的类型擦除呀,导致这两方法的特征签名是一致的,故无法编译通过)
在这里插入图片描述
下一章:java语法糖–自动装箱拆箱与遍历循环

发布了19 篇原创文章 · 获赞 3 · 访问量 3820

猜你喜欢

转载自blog.csdn.net/weixin_42792088/article/details/100168953