java 泛型

来源:互联网 发布:淘宝一键上传好不好 编辑:程序博客网 时间:2024/05/29 14:14
  • Java 泛型 <? super T> 中 super 怎么 理解?与 extends 有何不同?
  • List<?>List<T>的区别?

泛型是用来指定【类】所持有的【对象】的【类型】、方法所接受的参数的类型、所返回的对象的类型的。一般对泛型对象的操作是存储与获取(因为不确定泛型的对象的正确的类型嘛(∩_∩)

泛型用到的一些元素

命名规则

E - Element (通常代表集合类中的元素)
K - Key
V - Value
N - Number
T - Type
S,U,V etc. – 第二个,第三个,第四个类型参数……

通配符及限制

extends:泛型中,不管是接口还是类,用的都是 extends
super:

<?><T>的区别

<?>:用于使用
<T>:用于定义
比如声明一个类可以用class Plate<T>{},而在使用中可以使用Plate<? extends Fruit> plate = new Plate<Apple>(new Apple());

详细的解释

现在有四个类,分别是 Food,Fruit,Apple 和 Plate。其中 Apple 继承自 Fruit,Fruit 继承自 Food,Plate 是用来盛放这些东西的容器

T 是用于【定义】的,比如我定义一个可以盛放某种东西的盘子(Plate)

class Plate<T> {    T x;    // 我需要一个空构造器和一个赋值的构造器,使下面的演示代码更易理解    public Plate(){};      public Plate(T x){this.x = x;}    public void set(T x){this.x=x;}    public T get(){return x;}}

对于上面这个能存放特定东西的盘子,我自然可以用它来实例化一个只能存放水果的盘子

Plate<Fruit> plate = new Plate<Fruit>();// 一个只能存放水果的盘子,我自然能用它来存放苹果plate.set(new Apple());// 但是该盘子会认为存在里面的都是水果,而不是具体的对象类型,所以取出来的只能是【水果】这个总的类别,而不能是【苹果】Fruit fruit = plate.get();

一个只能盛放水果(也就是 Fruit 及其子类)的盘子

// 如果这么写,那该盘子只能被实例化为只能存放【水果】或者【某一种水果】(比如【苹果】)的盘子,而不能是其他的东西,比如【肉】class Plate<T extends Fruit> { ... }//或者说一个只能盛放 Fruit 及其父类的盘子class Plate<T super Fruit> { ... }

下面我需要一个盘子,我不知道该盘子的具体类型,但是我知道它只能用来存放【水果】或者是【某一种水果】,那我可以这么声明一个句柄,并在适当的时候为其赋值

// 该句柄可以指向的实例对象的类型有,Plate<Fruit> 和 Plate<Apple>// 【? extends】 被叫做上界通配符;同样的,【? super】被叫做下界通配符Plate<? extends Fruit> plate;// 这个上界通配符的副作用是只能【取】,不能【存】plate.get();  // successplate.set();  // error//反之,下界通配符只能【存】,不能【取】//下界通配符能存的是下界的子类,也就是说上下界通配符所谓的只能【存】和【取】,说的是【界】的子类

这里解释一下为什么上界通配符只能取不能存
因为现在编译器虽然知道这个盘子里装的一定是【水果】或者【它的子类】,但是并不知道它是个什么盘子
如果它是一个可以装任何水果的盘子,而我现在想存入【苹果】,这是可以的
但是,如果它是一个只能存放【苹果】的盘子,而我现在想存入【水果】,这是错误
就像是我可以把一个子类对象传入到一个接受父类对象作为参数的方法中,但是不可以把一个父类对象传入到一个接受子类对象的作为参数的方法中
简单的说,编译器不知道这个容器的具体类型,所以拒绝向容器中存入对象;但是知道容器里存放的是什么东西,所以可以取出对象。

原创粉丝点击