java泛型中遇到的一些问题

来源:互联网 发布:雕刻软件有哪些 编辑:程序博客网 时间:2024/06/05 02:59

Java的泛型和C++有很大不同,一开始学的时候确实很不适应

通常情况下,一个编译器处理泛型有两种方式:

    1.Code specialization。在实例化一个泛型类或泛型方法时都产生一份新的目标代码(字节码or二进制代码)。例如,针对一个泛型list,可能需要 针对string,integer,float产生三份目标代码。

    2.Code sharing。对每个泛型类只生成唯一的一份目标代码;该泛型类的所有实例都映射到这份目标代码上,在需要的时候执行类型检查和类型转换。

C++采用的是第一种机制,在运行时会给C++编译器会为每一个泛型类实例生成一份执行代码。这很方便,但会导致代码膨胀和安全性上的一系列问题

Java采用的是第二种机制,能够解决代码膨胀等在c++中出现的问题,但同时也带了一些复杂的问题,比如常见的这个案例


import java.util.ArrayList;

 

public class Test{

    public static void main(String[] args) {

       ArrayList<String> test = new ArrayList<String>();

       test.add("a");

        test.add("b");

       accept( test);

    }

 

    public static void accept(ArrayList<Object>  test) {

       for (Object o : test)

           System.out.println(o);

    }

 

这段代码编译器会报错,自己可以试一试

在Intellij idea报错:Error:(30,24) java: 不兼容的类型: java.util.ArrayList<java.lang.String>无法转换为java.util.ArrayList<java.lang.Object>

原因在于类型擦除。Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。

 

在编译之后,List<Object>和List<String>将变成List,Object和String类型信息对于JVM来说是不可见的。在编译阶段,编译器发现它们不一致,因此给出了一个编译错误

Java内部有翻译泛型表达式和翻译泛型方法的机制,很好的处理了类型擦除在调用和继承中出现的问题,使用桥方法解决了泛型在多态中问题

简单讲解桥方法:

看这个例子

classSPairextendsPair<String>{ 

          publicvoid setFirst(String First){....} 

}

这里子类准备重写超类中的setFirst方法,但经过类擦除,Pair<String>中的

publicvoid setFirst(StringFirst)

成为

publicvoid setFirst(ObjectFirst)

我们知道要实现覆盖,除了可协变的返回类型,其他的方法的签名和返回类型必须和超类一致,然而我们现在的子类意图覆盖的方法的方法签名与超类一致,如果编译器不做处理则会导致覆盖失败,也就造成了泛型在多态中问题

编译器当然使用了一定的解决方案——桥方法

对于这种情况,编译器自动为子类生成了一个桥方法:

publicvoid setFirst(ObjectFirst){

setFirst(String First)//调用自己的方法}

对于由泛型引起的其他问题,根据这个思路都可以解决。

 

 

原创粉丝点击