泛型简析——(一)泛型是什么?

泛型定义

泛型,即”不确定的参数类型”,使代码可应用于多种不同的类型,而不再是仅限于一种确定的类型。泛型使我们可以通过参数确定类要使用的类型。

泛型的使用方法

泛型类

泛型类的定义需要将类型参数列表放在类名的后面

class className<Type1,Type2...>{}

例:

public class Test<T> {
    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
    public static void main(String[] args){
        Test<A> test = new Test<A>();
        test.setT(new A());
        test.getT().showMessage();
    }
}
class A{
    public void showMessage() {
        System.out.println("This is class A.");
    }
}
//运行结果:
//This is class A.

在创建Test实例的时候,我传进去一个类型参数A ,这样Test就知道我需要用这个类是什么类型,并且我不需要对取出的t进行强转,它依旧可以执行这个类自己的方法,因为它返回的就是一个A的实例,而不是Object。

泛型方法

泛型方法需要将类型参数列表放在返回值的前面,使用时可以用在返回值上,也可以用在方法参数中

<Type1,type2> returnType methodName(){}

例:

public class Test {
    public static <T> void viewClassMsg(T t){
        System.out.println(t);
    }
    public static void main(String[] args){
        viewClassMsg(new A());
    }
}
class A{
    @Override
    public String toString() {
        return "This is class A.";
    }
}
//运行结果
//This is class B.

这样,我们就可以通过泛型来指定应用需要使用的类型,而不需要使用具体的类型。

泛型通配符

在声明变量及定义方法时可以使用泛型通配符“?”,表示任意泛型类型,但是取出时要小心,正因为能表示任意泛型类型,它不能确定它取出来的是否和你所需要的那种,所以它只能以Object的方式取出来。
泛型简析——(一)泛型是什么?_第1张图片
如图所示,程序无法找到view这个方法,因为它不确定取出来的这个值是什么类型,所以不能判断是否拥有这个方法。

上界与下界

使用泛型通配符范围过大,或许我们并不需要这么大的范围,仅仅需要限定泛型的一小范围,那么我们可以使用extends/super来进行限制

  • 上界:extends
    使用extends关键字可限制泛型的上界,即只允许参数类型为继承了某个类或实现了某个接口的类。
public class Test{
    public static void viewMsg(List<? extends  A> list){
        for(A element : list){
            System.out.println(element.msg);
        }

    }
    public static void main(String[] args){
        List<A> list0 = new ArrayList<>();
        list0.add(new A());
        viewMsg(list0);
        List<B> list1 = new ArrayList<>();
        list1.add(new B());
        viewMsg(list1);
    }
}
class A{
    protected String msg = "蠢猪镜";
}
class B extends A{
}
//运行结果:
//蠢猪镜
//蠢猪镜

可以看到,不仅是list0可以传递进去,list1也可以,因为限制了泛型的上界,只要是持有类型A及其子类的List都可以作为参数传递进去,这就是所谓的上界。

  • 下界:super
    使用super关键字可以限制泛型的下界,即限制泛型的类型参数为指定类的本身或其父类。
public class Test{
    public static void viewMsg(List<? super  B> list){
        for(Object element : list){
            System.out.println(element);
        }
    }
    public static void main(String[] args){
        List<A> list0 = new ArrayList<>();
        list0.add(new A());
        viewMsg(list0);//将List的实例传递进去,可行
        List<B> list1 = new ArrayList<>();
        list1.add(new B());
        viewMsg(list1);//将List的实例传递进去,可行
        List<C> list2 = new ArrayList<>();
        list1.add(new C());
        //viewMsg(list2);---这里报错,因为C是B的子类,而泛型要求为B及其父类
    }
}
class A{
    @Override
    public String toString() {
        return "蠢猪镜";
    }
}
class B extends A{
    @Override
    public String toString() {
        return "蠢海星";
    }
}
class C extends B{
}

在遍历List中元素时,我尝试使用B或者A去作为增强for的需要遍历的类型,但是却报错了。后来我想清楚了,因为使用的这些类在其上还有父类,而子类中可能拥有一些父类没有的值或方法,这样就不能直接用这种还有父类的类去作为遍历的类型,需要使用Object类。

总结

泛型的出现给开发带来了许多的便利,让我们可以在一段代码中使用不同的类型,而不用去针对一个类型去写大量相同的代码。并且使用泛型也使代码更加简洁易读。但是在泛型中,还有其他的东西需要去学习,如泛型的类型擦除,类型擦除是泛型实现过程中一个重要的机制,下一个博客将会对类型擦除作出详细的讲解。

你可能感兴趣的:(学习,Java)