java 返回 extends t_Java泛型中 <?>、<? extends T>、<? super T>的区别

Java泛型中的?指通配符,泛指所有类型。而 extends T>指的是上界通配符,? super T指的是下界通配符。

1 为什么要用通配符和边界?

举个例子,我们假设有一个Cat类表示所有的猫科动物,那么显然加菲猫类Garfield是Cat的一个子类。如果我们有一个猫科动物的笼子List,我们理所当然地认为这个笼子也可以关加菲猫。但是,下面这行代码却在编译期报错了。

List cats = new ArrayList();

所以,我们可以知道,就算容器中存放的对象类型有继承关系,容器间却是没有继承关系的。为了让容器间也存在类似的继承关系,通配符边界就应运而生了。

2 什么是上界?

List extends T>表示这个List对象可以存放T和T的一切子类对象,由此,编译器认为List extends T>是List的父类,所以我们按照如下方式赋值是不会报错的。

List extends Cat> cats = new ArrayList();

然而,使用<?extends Cat>定义的List是不可以再存放任何元素的,因为编译器仅仅知道你集合中对象的类型都是?,具体是啥类型并不知道,所以肯定不能让你乱放元素,万一你放了个Object对象,那集合中的对象类型就乱套了,不再是Cat或Cat的子类。

使用<?extends Cat>定义的List的get()方法正常,因为取出来的元素都可以向上转型成Cat对象。

3 什么是下界?

List super T>表示这个List对象可以存放T和T的一切父类对象。但是,List super Cat>是List的父类,但是却不是List的父类。也就是说,下面这行代码编译期就会报错。

List super Cat> cats = new ArrayList();

但是这样赋值就不会报错:

List super Cat> cats = new ArrayList();

使用 super Cat>定义的List的get()方法会部分失效,因为所有取出来的对象都会转型为Object对象,从而丢失对象原来的信息。set()方法正常。

import java.util.ArrayList;

import java.util.List;

public class AnimalCatGarfield {

public static void main(String[] args) {

List animals = new ArrayList<>();

List cats = new ArrayList<>();

List garfields = new ArrayList<>();

animals.add(new Animal());

cats.add(new Cat());

garfields.add(new Garfield());

// 编译出错,extendsCatFromAnimal只能赋值Cat或Cat子类的集合

List extends Cat> extendsCatFromAnimal = animals;

// 编译成功

List super Cat> superCatFromAnimal = animals;

// 下面两行均编译成功

List extends Cat> extendsCatFromCat = cats;

List super Cat> superCatFromCat = cats;

// 编译成功

List extends Cat> extendsCatFromGarfield = garfields;

// 编译出错,superCatFromGarfield只能赋值Cat或Cat的父类集合

List super Cat> superCatFromGarfield = garfields;

// 测试add方法

// 下面三行均编译失败,除了null以外,任何元素都不能被添加进 extends T>集合内

extendsCatFromCat.add(new Animal());

extendsCatFromCat.add(new Cat());

extendsCatFromCat.add(new Garfield());

// 编译失败,只能添加Cat或Cat子类的集合

superCatFromCat.add(new Animal());

// 下面两行均编译成功

superCatFromCat.add(new Cat());

superCatFromCat.add(new Garfield());

// 测试get方法

// 所有super操作都能够返回元素,但是泛型丢失,只能返回Object对象

// 以下extends操作能够返回元素

Object catExtends2 = extendsCatFromCat.get(0);

Cat catExtends1c = extendsCatFromCat.get(0);

// 编译出错,虽然Cat集合从Garfield赋值而来,但是类型擦除后,是不知道的

Garfield garfield1 = extendsCatFromGarfield.get(0);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值