您的位置:首页 > 其它

泛型

2016-05-26 23:34 260 查看

泛型

基本使用略。

擦除

没有指定泛型,其最终在一般情况下会转换成Object。这就是泛型的擦除。如:

private abstract class Father<T>{
T str;
public abstract void test();
}
private class Child1<T,T1> extends Father{
T1 str1;
@Override
public void test() {

}
}
public void test(){
Child1<String,Intent> child1 = new Child1<>();
Object str = child1.str;//str为Object类型
Intent intent = child1.str1;//str1为Intent类型,是通过泛型指定的
}

这里在extends Father时并没有指定Father的泛型,所以其内部的str类型就被转换为Object了。而在new Child1时指定了泛型String,Intent,因此str1是Intent类型的。

泛型的擦除会发生在两个地方:1,子类实现或实现时没有为父类指定泛型;2,使用者在使用时,没有指定泛型。此时会统一使用Object对待。

继承时的泛型

父类如果定义了泛型,子类在继承或实现时,必须指定全部的泛型或者都不指定。如上面的Child1,是都没指定。都指定的示例如下:

private abstract class Father<T,T1>{
T str;
T1 t1;
public abstract void test();
}
private class Child1<T,T1> extends Father<T1,T>{//父类有泛型,并且定义了。那么子类必须也指定,因为父类的泛型来自于子类
T str1;
@Override
public void test() {

}
}
public void test(){
Child1<String,Integer> child1 = new Child1<>();
//此时child1中的str为Integer类型,t1为String类型
}
在定义Child1类时,父类指定了泛型,它又来自于子类,子类的泛型在定义时指定,因此Child1必须定义泛型<T,T1>——这两个名字与父类的相同,但顺序可以不一致。
在new Child1时 ,为泛型指定了具体的类型。所以Father中的T,T1都有了具体的类型。

当然,可以在继承的时候,直接为Father指定泛型,此时Child1可以不使用泛型。也就是说:父类的泛型来自于子类——除非继承或实现时直接指定,而子类的泛型来自于使用时使用者指定。不能父类需要泛型,而子类却没有指定。

注意事项

1,使用泛型定义数组时,只能用来声明,不可以用来定义。即T[] ta;是合法的,但ta = new T[3];是错误的。这也是为什么ArrayList中使用的是Object[]数组来存储其中的元素,而不是直接使用泛型数组。如下是ArrayList#get()源码:

@SuppressWarnings("unchecked") @Override public E get(int index) {
if (index >= size) {
throwIndexOutOfBoundsException(index, size);
}
return (E) array[index];//其中array是Object[]
}

2,泛型没有多态。但可以使用通配符?达到类似多态的效果。如:

ArrayList<Father> list = new ArrayList<Child1>();//报编译错误
ArrayList<?> list = new ArrayList<Child1><child1>();//可正常使用
</child1>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: