JavaSE笔记之<泛型再理解(简化版)>

来源:互联网 发布:windows音量图标不见了 编辑:程序博客网 时间:2024/05/16 07:39

java中有类(class)、方法(method)、域(field) 、接口 它们都能使用泛型,但域的泛型要和类关联(且除了静态数据成员以外,因为它不和实例相关联,泛型类是和实例相关联的)。

简单介绍下泛型的一些基本术语,以ArrayList<E>ArrayList<Integer>做简要介绍:

整个成为ArrayList<E>泛型类型

ArrayList<E>中的 E称为类型变量或者类型参数

class Generic<E>{}中的E称为泛型参数

整个ArrayList<Integer> 称为参数化的类型

ArrayList<Integer>中的integer称为类型参数的实例或者实际类型参数

·ArrayList<Integer>中的<Integer>念为typeof   Integer

ArrayList称为原始类型

①边界

边界是类型参数的一种限制条件(约束),一般都是限制某个参数为某个类型的子集(定义的时候),为了执行这种限制,java泛型重用了extends关键字。

类型边界在泛型类、泛型接口和泛型方法中都可以使用,不过要注意下面几点:

1、不管该限定是类还是接口,统一都使用关键字 extends,泛型参数不能给出超类型边界(即super)

2、可以使用&符号给出多个限定

如class CanineHero <P extends superHearing & SuperMell> 

extends后面是一个确切类型

自限定:Class Generic <T extends Generic<T>>{}  Generic<T>相当于Generic<String>是一个参数类型为T的类型,是T的边界

②通配符

List<?> 包含的是任意类型的List(无界通配符)

List<? extends Number>包含的是Number或者其子类的List(上界通配符)

List<? super Integer> 包含的是Integer或者其父类的List(逆变,下界通配符)


这个其实已经是指定了类型参数了,指定类型参数包括两种,一是直接确定类型参数;而是用通配符。因此可以是List<String>或者List<?>这样


③泛型擦除

由于java和C++实现泛型方式不一样,java是code share的方式,即只有一个字节码对应多种不同的类型。实现此方式需要用到泛型擦除,这是java实现泛型的底层原理。

如何擦除?

1.将所有的泛型参数用其最左边界类型(限定类型)替换。<T>等同于<T extends Object>即T会用Object代替
2.
移除所有的类型参数。

    class Collections {            public static <A extends Comparable<A>>A max(Collection <A> xs) {   //<>中的A不用管,只有定义的时候方法前面的是泛型参数,方法内部的是类型参数          Iterator <A> xi = xs.iterator();             A w = xi.next();             while (xi.hasNext()) {               A x = xi.next();               if (w.compareTo(x) < 0) w = x;             }             return w;           }         }     

类型擦除后:

    class Collections {            public static Comparable max(Collection xs) {             Iterator xi = xs.iterator();             Comparable w = (Comparable) xi.next();             while (xi.hasNext()) {               Comparable x = (Comparable) xi.next();               if (w.compareTo(x) < 0) w = x;             }             return w;           }         }     

首先A被Comparable<A>代替  静态方法内部不用管,则A w = xi.next(); 类型擦除后变成Comparable<A> w = xi.next();

第二步移除所有的类型参数 Comparable<A> w = xi.next(); 变成 Comparable w = xi.next();

④类型擦除引起的问题及解决方法

先检查,再编译。检查针对的是引用。

既然说类型变量会在编译的时候擦除掉,那为什么我们往ArrayList<String> arrayList=new ArrayList<String>();所创建的数组列表arrayList中,不能使用add方法添加整形呢?不是说泛型变量Integer会在编译时候擦除变为原始类型Object吗,为什么不能存别的类型呢?既然类型擦除了,如何保证我们只能使用泛型变量限定的类型呢?

java是如何解决这个问题的呢?

java编译器是通过先检查代码中泛型的类型,然后再进行类型擦除,再进行编译的。

    public static  void main(String[] args) {              ArrayList<String> arrayList=new ArrayList<String>();              arrayList.add("123");              arrayList.add(123);//编译错误          }  
因为arrayList是ArrayList<String>类型的引用,编译器会查看上下文,检查到第三行arrayList.add(123)时,由于其中加的是整型数据,所以自动报错。

接着会编译。


部分参考:http://blog.csdn.net/lonelyroamer/article/details/7868820

0 0
原创粉丝点击