Java编程思想之泛型小结

看这一章花了好些时间,直到现在依然有一些不明朗的地方。如果有个人认识不正确的地方,烦请指出。
1.
引用
有许多原因促成了泛型的出现,而最引人注目的一个原因,就是为了创造 容器类

class Automobile {}
public class Holder1 {
    private Automobile a;
    public Holder1(Automobile a) {this.a = a;}
    public void set(Automobile a) { this.a = a; }
    public Automobile get() { return a; }
}
这个类持有一个Automobile类型的对象a,但重用性很差,如果要持有其他非Automobile类型需重写。

public class Holder2 {
    private Object a;
    public Holder2(Object a) { this.a = a; }
    public void set(Object a) { this.a = a; }
    public Object get() { return a; }
}
这个类持有Object类型的对象a,但可以往里随意set各种类型的对象。但我们只需要持有一种特定类型,并且想保证类型的正确性,所以请用泛型吧。

public class Holder3<T> {
    private T a;
    public Holder3(T a) { this.a = a; }
    public void set(T a) { this.a = a; }
    public T get() { return a; }

    public static void main(String[] args) {
        Holder3<Pet> h3 = new Holder3<Pet>(new Cat());
        h3.set(new Dog());
        Pet a = h3.get();
    }
}
这个类持有的是T类型的对象a,当创建Holder3对象时,只需告诉编译器要使用Pet类型。并且当h3对象被创建出来,它就只能持有Pet类型或其子类型,如本例中的Cat和Dog,但你不能给它set People类型的对象,即编译器会做类型检查。

2.Java泛型局限之一,基本类型无法作为类型参数。但可以使用包装类型,与基本类型进行转换。

3.关于擦除:
引用
在泛型代码内部,无法获得任何有关泛型参数类型的信息
举个例子就是new ArrayList<String>().getClass()与new ArrayList<Integer>().getClass()所得到的是相同的实例。
引用
Java泛型是使用擦除来实现的,这意味着当你在使用泛型时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。因此List<String>和List<Integer>在运行时事实上是相同的类型。这两种形式都被擦除成它们的“原生”类型,即List。


4.关于边界:
引用
边界使得你可以再用于泛型的参数类型上设置条件。

因为擦除了类型信息,所以类似List<T>这种无界泛型参数的写法实际运行时只认为参数是一个Object类型。设置泛型边界使用 extends关键字,如:class Colored<T extends HasColor>。

5.关于通配符“?”:
假设有如下的类继承关系:
class Fruit {}
class Apple extends Fruit {}

在泛型的使用中,却不能这样初始化:List<Fruit> list = new ArrayList<Apple>();
这里用个人做的练习28的代码来理解用法,注意里面关键字super和extends的使用:
class GenericSet<T> {
    public void setMethod(T param) {
    }
}

class GenericGet<T> {
    private T param;
    public T getMethod() {
        return param; 
    }
}

public class Practise28 {

    static <T> void setMethod(GenericSet<? super T> param, T item ) {
        param.setMethod(item);
    }
    
    static <T> void getMethod(GenericGet<? extends T> param) {
        param.getMethod();
    }
    
    public static void main(String[] args) {
        GenericSet<Fruit> individual1  = new GenericSet<Fruit>();
        GenericGet<Fruit> individual2  = new GenericGet<Fruit>();
        setMethod(individual1, new Apple());
        getMethod(individual2);
    }
}


6.关于自限定类型:
使用个人做的练习34的代码来理解(不要吐槽命名。。。):
abstract class MyAbstract<T extends MyAbstract<T>>
{
    abstract T method(T i);
    
    T invoke(T i) {
        System.out.println(i.getClass().getSimpleName());
        return method(i);
    }
}

public class Practise34 extends MyAbstract<Practise34> {
    
    public static void main(String[] args) {
        System.out.println(new Practise34().invoke(new Practise34()));
    }

    @Override
    Practise34 method(Practise34 i) {
        return i;
    }
}

你可能感兴趣的:(java,泛型,边界,自限定类型,擦除)