深入Java泛型(三):泛型的上下边界

下面的代码是会出现异常的:

List<?> poems = new ArrayList();

poems.add(“life is a song”);

?表示这个List集合中保存的元素是未知类型的,Java不允许把对象放进一个未知类型的集合中,正常的:

package generic;

import java.util.ArrayList;

import java.util.List;

/**

  • Created by zhoujie on 1/25/16.

*/

public class First {

/**

  • ? 都处理成Object, 处理所有类型

  • 可以通过返回一个 List<?>的值, 都被当成Object来处理

  • @param c

*/

public static void display(List<?> c) {

for (int i = 0; i < c.size(); i++) {

// c.get(i) 是Object类型的

System.out.println(c.get(i));

}

}

public static void main(String[] args) {

List poems = new ArrayList<>();

poems.add(“life is a song”);

poems.add(“some one like you”);

poems.add(“you are so beautiful”);

display(poems);

}

}

List<? extends Animal>, 通配符的上限

Animal.java:

public abstract class Animal {

public abstract void sing(Perform p);

}

Cat.java:

public class Cat extends Animal {

@Override

public void sing(Perform p) {

System.out.println(“Hello, audience, I’m a Cat.”);

}

}

Dog.java:

public class Dog extends Animal {

@Override

public void sing(Perform p) {

System.out.println(“Hello, audience, I’m a dog.”);

}

}

Perform.java:

public class Perform {

public void perform(List animals) {

for (Animal a : animals) {

a.sing(this);

}

}

}

下面写一个类测试一下上面的几个类:

public class TestGeric {

public static void main(String[] args) {

List dogs = new ArrayList<>();

Perform p = new Perform();

dogs.add(new Dog());

p.perform(dogs); // 此处代码编译出现异常

}

}

List不能和perform中的参数 List animals对应起来,说明List并不是List的子类型,可以将Perform类的代码改成:

public class Perform {

public void perform(List<?> animals) {

for (Object o : animals) {

Animal a = (Animal)o;

a.sing(this);

}

}

}

这样的改进使用了泛型却还需要进行强制类型转换,略显繁琐。

继续改进Perform类:

public class Perform {

public void perform(List<? extends Animal> animals) {

for (Animal a : animals) {

a.sing(this);

}

}

}

终于引出了可爱的List<? extends Animal>,?表示的类型可以是Animal类型和Animal的子类。可以把Animal称为这个通配符(?)的上限(upper bound)。

和一开始讲的List<?>一样,List<? extends Animal> 通常也是当作函数的参数来指定,

public void addMonkey(List<? extends Animal> animals) {

// 下行代码出现编译错误

animals.add(0, new Monkey());

}

带 ?的泛型表达一般都当做方法参数或方法返回值来使用,也就是本笔记中讲述的泛型方法相关。

还有就是,如下代码:

public class Apple {

T col;

public static void main(String[] args) {

//类型只能是Number类型或Number的子类型

Apple ai = new Apple<>();

//编译错误

//Apple as = new Apple<>();

}

}

<? super E>通配符的下限

来看一段代码:

public static T copy(Collection<? super T> dest, Collection src){

T last = null;

for (T ele : src) {

last = ele;

dest.add(ele);

}

return last; //返回一个T类型的变量

}

/*

<? super Type> 通配符 ? 表示它必须是Type本身,或是Type的父类 */ // 栗子 List ln = new ArrayList<>(); List li = new ArrayList<>(); li.add(2016); // 此处可准确地知道最后一个被复制的元素是Integer类型 // 与src集合的元素类型相同 Integer ele = copy(ln, li); 在集合框架中的 TreeSet有一个构造器也用到了这种设定通配符下限的语法, TreeSet(Comparator<? super E> c) ## 总结 互联网大厂比较喜欢的人才特点:对技术有热情,强硬的技术基础实力;主动,善于团队协作,善于总结思考。无论是哪家公司,都很重视高并发高可用技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。其实我写了这么多,只是我自己的总结,并不一定适用于所有人,相信经过一些面试,大家都会有这些感触。 **另外本人还整理收藏了2021年多家公司面试知识点以及各种技术点整理 ** **下面有部分截图希望能对大家有所帮助。** ![在这里插入图片描述](https://img-blog.csdnimg.cn/img_convert/235b6482f5997b78590fda86ebc24557.webp?x-oss-process=image/format,png) 设定通配符下限的语法, TreeSet(Comparator<? super E> c) ## 总结 互联网大厂比较喜欢的人才特点:对技术有热情,强硬的技术基础实力;主动,善于团队协作,善于总结思考。无论是哪家公司,都很重视高并发高可用技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。其实我写了这么多,只是我自己的总结,并不一定适用于所有人,相信经过一些面试,大家都会有这些感触。 **另外本人还整理收藏了2021年多家公司面试知识点以及各种技术点整理 ** **下面有部分截图希望能对大家有所帮助。** [外链图片转存中...(img-2KrINfy6-1714738164063)] > **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/topics/618154847)收录**
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值