您的位置:首页 > 职场人生

黑马程序员-泛型总结

2012-07-23 23:17 169 查看
----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

1. 为什么要使用泛型

因为

1)使用泛型意味着编写的代码可以被很多个不同类型的对象所重用。

2)使用泛型之后可以减少类型转换的风险

2.泛型类

1) 类定义中的类型变量指定了方法的返回类型已经域和局部变量的类型。

2) 在生成泛型类的实例时,没有强制要求要去设置其类型参数,只是不设置类型参数时,会给出警告:

如"Test is a raw type. References to generic type Test<T> should be

parameterized"

3.泛型方法

1) 泛型方法可以定义在普通类中,也可以定义在泛型类中

2)泛型方法的调用,有2种方式,一般使用第2种方式。如:

//1. 在方法前加上<String>

ArrayAlg.<String>getMiddle(names);

//2. 在方法不加上<String>,编译器会推断出T的类型是String,这样调用也不会有警告提示

ArrayAlg.getMiddle(names);

4.泛型限定

 1)目的: 使用泛型边界控制(泛型限定)是为了使用T上的方法,如果不限定则不能调用T上的任何代码。

例:T extends Comparable 表明T只能是实现了Comparable接口的类或者接口。这是对泛型边界的控制。

这时就可以调用T上的compareTo方法,因为编译器知道T实现了omparable接口。

2)一个类型变量可以有多个限定,如:

T extends Comparable & Serializable,多个限定之间使用&分割。

3)跟java的继承一样,对泛型的限定只能有一个是限定类,可以多个限定接口,并且限定类必须放在类型变量的

限定中的第一个

如:T extends boundTypeClass1 & inteface1 & interface2

如果是 T extends boundTypeClass1 & boundTypeClass2 则会报错

5.泛型代码与虚拟机

1)虚拟机没有泛型类型对象,所有的对象都是普通对象。如,没有ArrayList<String>.class 和ArrayList<Integer>.class

的区别,二者在虚拟机中都是Arraylist.class.即泛型类型的信息在jvm中被擦除了(也即类型参数被擦除)。

2)当定义一个泛型类型时, jvm都会自动地为该泛型提供一个相应的原始类型(raw type).原始类型的名字就是删除类型参数后的

泛型类型名。如:Pair<String>的原始类型就是Pair.

3)在jvm中,泛型类型变量会被擦除,并替换为限定类型,如果没有指定限定类型,在替换为Object。如Pair<T>,因没有指定限

定类型,所以类Pair中所以的T会被替换成Object. 如 方法 public T getFirst(){return first} 会被替换成public Objct

getFirst(){return first}.

如果指定了限定,那么原始类型会用第一个限定类型的变量来替换。如:

public class Interval<T extends Comparable & Serializable> implement Serializble{

public Interval(T first , T second){

....

}

private T lower;

private T upper;

}

原始类型Interval替换后如下(也即类中的T被第一个泛型限定Comparable替换):

public class Interval implement Serializble{

public Interval(Comparable first , Comparable second){

....

}

private Comparable lower;

private Comparable upper;

}

6. 将泛型变量赋给普通变量和把普通变量赋给泛型变量的问题。

7. java泛型需要考虑的一些限制

1) 不能用基本类型实例化参数类型。如没有Pair<double>,只有Pair<Double>.

2) 运行时类型查询只使用于原始类型。如if(a instanceof Pair<String> ) 跟if(a instanceof Pair) 是一样的

3) 参数化数组不合法。如 Pair<String>[] ps = new Pair<String>[10]; //error

但是在方法返回的时候可以返回 T[];

4) 不能实例化类型变量

如: new T() 或 T.class;//error.

5) 泛型类的静态上下文中类型变量无效。

如声明一个 public static T getxxx(){}的方法会报错。

8. 泛型的协变和逆变,即: <T extends SomeType > 和<T super SomeType>

1)协变和逆变的作用:

是在两个泛型之间建立某种类型的向上转型关系。因为普通类的继承关系直接在泛型中使用是行不通的。

如:Number 是Integer 的父类。Number n = new Integer();这种使用方式没有问题,但是如果有一个泛型接口

public interface Box<T> {

public T get();

public void put(T element);

public void put(Box<T> box);

}

注:BoxImpl代码省略

Box<Integer> iBox = new BoxImpl<Integer>(3);

Box<Number> nBox = iBox;

上面的语句会报错。但是使用

Box<? extends Number> nBox = iBox; 就可以了。

2)注意事项:

协变只能取数据,不能set数据。而逆变则相反,可以设置数据,不能用于取数据

9. 无界通配符<?>

1)为什么要用无界通配符?

个人感觉用处不大,唯一能体会到的用处是:在使用遗留代码或者一些第3方工具类的时候,去掉非泛型代码的警告。如

Query query = "";

List resultList = query.getResultList();

该句会有警告。因为getResultList不是泛型化的List,但是可以使用以下语句来去除警告:

List<?> resultList = query.getResultList();

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐