Java泛型实现原理

前言

首先在直到泛型马,就是一个类型变量,可以放入任何类型得东西,Java是强类型的不得乱加类型,使用前必须指定类型是什么否则就报错无法编译,而泛型就可以理解为一个类型参数,就一个参数用的时候指定这恶参数的是什么就可以,也就是用的时候再指定类型,这样子也不会报错。

历史

强类型有哪些弊端也就很明显,有的时候需要类型是运行的时候才知道的,比如写List接口啥的,肯定不能事先知道要放的是什么类型,又要满足Java的多态特性也就是说放什么都可以,这就是难到强类型了,还好有Object对象,所有对象都是继承于这个对象,又因为子类可以直接赋值给父类然后又赋值给子类时所有信息还是子类的信息,也就是说可以把Object当作一个万能的类型什么类型都可以保存《子类可以直接赋值给父类,但》。泛型没有提出之前都是用Object来实现通用类型的,比如容器List里面定的数据类型就是Object然后输入什么引用类型都可以,不会报错,因为都可以赋值给父类Object,当返回时再强制转换就可以,比如

  List  list = new List();
    list.add(1);
    list.add("1");
    for(int i :list){
        System.out.println(i);
    }

赋值也就是说List本意就是存放一个整型的List,但是不小心写成了"1",就是一个字符串,而又因为List放什么类型都不会报错,所以编译不会出错,但是运行的时候就会抛出异常,类型转换异常,因为String类型不能转换为int类型。这就是说不安全的,编译的时候不出错,运行才出错,泛型就被提出来了
如果用泛型的话上面的代码就是这样

List<Integer>  list = new List<>();
list.add(1);
list.add("1");
for(int i :list){
    System.out.println(i);
}

如果这么写,编译的时候就会报错,不能通过编译也就是不会在运行的时候异常了,因为定义list的时候就指定了list里面的类型是Integer类型如果赋值字符串类型就是报错。
所以泛型的作用就是把类型错误控制在编译阶段,不在运行阶段,保证了类更加安全。还可以看到一个东西,就是泛型的作用就是在编译阶段。

类型擦除

上面看到,泛型作用在编译阶段,指定一个容器放啥类型后,如果赋值类型不对,在编译阶段就报错。其实java对这个泛型的实现就是类型擦除,也就是说在编译阶段后到虚拟机里面就把泛型给擦除掉了,不存在类型参数,将类型参数变成原始类型通常就是Object,编译后泛型就不存在了
如下代码

class  < T > A{
  private T a;
}

编译后到虚拟机中后变成

class   A{
  private  Object  a;
}

类型被擦除,泛型转换成类型Object,如果类型变量有限定,那么原始类型就用第一个边界的类型变量来替换。
你在类里面定义的泛型会转换为一个Object,(如果看过集合框架就会看到这一点,集合里面保存的引用类型就是一个Object,然后类型转换),然后输出的泛型,比如List里面如果用泛型的话,get()出来的类型是Object类型,由于你使用了泛型所以在编译阶段编译器会自动帮你加上一个类型强制转换的,强制转换成泛型指定的对象,所以就这样,和原来没有泛型时是一样的做法,只是加了泛型会在编译阶段检查一下,所以类会更加安全。
这个泛型通过类型擦除类实现的并不是真正的泛型所以java中的泛型叫伪泛型,只是为了在编译阶段是检查类型而已确保了类更加安全。

继承和桥方法

然后通过这个类型擦除会发现,继承咋办,泛型到了虚拟机后就是原始类型了。
加入这样子继承

class DateInter extends Pair<Date> 

然后重写有泛型的方法,由于泛型的类型擦除,比如重写下列方法

public T getValue() {
		return value;
	}

然后重写


	@Override
public Date getValue() {
		return value;
	}

由于类型擦写,父类的方法会变成

public Object getValue() {
		return value;
	}

这就不是重写了,是重载,类型不一样了,于是JVM采用了一个特殊的方法,来完成这项功能,那就是桥方法,
就是说在编译阶段,编译器会对中类型的重写自动添加一个和父类一样类型的方法,然后调用我们自己写的方法,也就是说我们写的@Override就是个幌子,其实是编译器帮我们加的然后调用我们自己的方法。

更加详细看着写得不错良心《java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值