个人主页→VON
收录专栏→java从入门到起飞
目录
一、前言
二、泛型通配符简要概述
基本概念
无界通配符 (?):
上限通配符 (? extends T):
下限通配符 (? super T):
三、思考
四、综合练习
Animal类及其javabeen
Cat类
Dog类
HuskyDog类
LihuaCat类
PersionCat类
TeddyDog类
Text1类
一、前言
泛型的学习就到此为止了,希望能够通过这一综合练习来理解泛型的应用。
二、泛型通配符简要概述
Java中的通配符(wildcard)是用来表示未知类型的语法符号,它在使用泛型时非常有用,尤其是在处理不确定具体类型的集合时。通配符可以让你编写更加灵活的代码,同时也保持类型安全性。
基本概念
Java中的通配符主要有三种形式:
无界通配符 (?
):
这是最基本的通配符,表示任何类型。当你不知道或者不关心具体是什么类型时,可以使用无界通配符。
例如:List<?>
可以接受任何类型的 List
,如 List<String>
、List<Integer>
等。
上限通配符 (? extends T
):
这个通配符表示“某种类型或者是 T
的子类型”。它主要用于接收数据,但不允许插入数据(除非是 null
),因为这可能会导致类型不匹配的问题。
例如:List<? extends Number>
可以接受 List<Integer>
、List<Double>
等,因为 Integer
和 Double
都是 Number
的子类型。
下限通配符 (? super T
):
这个通配符表示“某种类型或者是 T
的超类型(即父类型)”。它主要用于向集合中插入数据,但不允许从中提取数据(除了 Object
类型)。
例如:List<? super Integer>
可以接受 List<Object>
或者 List<Number>
,因为 Object
和 Number
都是 Integer
的超类型。
三、思考
如果只让它接受我们所需要的数据类型要如何改进呢?
此时就可以通过泛型的通配符
?表示不确定的类型
可以进行类型的限定
?extends E:表示可以传递E或者E所有的子类类型
?super E:表示可以传递E或者E所有的父类类型
应用场景:
1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口
2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以使用泛型的通配符
泛型的通配符
关键点:可以限定类型的范围
四、综合练习
这个题看似复杂其实一点也不简单
Animal类及其javabeen
package ArrayDemo.GenericsText;
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
public String toString() {
return "Animal{name = " + name + ", age = " + age + "}";
}
}
Cat类
package ArrayDemo.GenericsText;
public abstract class Cat extends Animal{
// 1.继承抽象类,重写里面所有的抽象方法
// 2.本身Cat也是一个抽象的,让Cat的子类再重写抽象方法
// 此时我们采用第二种处理方法
// 因为猫的两个子类中的eat方法还是不一样的
}
Dog类
package ArrayDemo.GenericsText;
public abstract class Dog extends Animal{
}
HuskyDog类
package ArrayDemo.GenericsText;
public class HuskyDog extends Dog{
@Override
public void eat() {
System.out.println("一只加做"+getName()+"的"+getAge()+"岁的哈士奇,正在吃骨头,边吃边拆家");
}
}
LihuaCat类
package ArrayDemo.GenericsText;
public class LihuaCat extends Cat{
@Override
public void eat() {
System.out.println("一只叫做"+getName()+"的"+getAge()+"岁的梨花猫,正在吃鱼");
}
}
PersionCat类
package ArrayDemo.GenericsText;
public class PersionCat extends Cat{
@Override
public void eat() {
System.out.println("一只叫做"+getName()+"的"+getAge()+"岁的波斯猫,正在吃小饼干");
}
}
TeddyDog类
package ArrayDemo.GenericsText;
public class TeddyDog extends Dog{
@Override
public void eat() {
System.out.println("一只加做"+getName()+"的"+getAge()+"岁的泰迪,正在吃骨头,边吃边蹭");
}
}
Text1类
package ArrayDemo.GenericsText;
import java.util.ArrayList;
public class Text1 {
public static void main(String[] args) {
ArrayList<PersionCat> list1 = new ArrayList<>();
ArrayList<LihuaCat> list2 = new ArrayList<>();
ArrayList<HuskyDog> list3 = new ArrayList<>();
ArrayList<TeddyDog> list4 = new ArrayList<>();
// 需求一
keepPet1(list1);
keepPet1(list2);
// keepPet1(list3);
// keepPet1(list4);
// 需求二
// keepPet2(list1);
// keepPet2(list2);
keepPet2(list3);
keepPet2(list4);
// 需求三
keepPet3(list1);
keepPet3(list2);
keepPet3(list3);
keepPet3(list4);
}
// 要求1:该方法能养所有的猫但是不能养狗
public static void keepPet1(ArrayList<? extends Cat> list){
}
// 要求2:该方法能养所有的狗但是不能养猫
public static void keepPet2(ArrayList<? extends Dog> list){
}
// 要求3:该方法能养所有的动物,但是不能养其他
public static void keepPet3(ArrayList<? extends Animal> list){
}
}
要仔细看清楚Animal、cat、dog类都是抽象类,因为子类的方法没有一样的。主要是通配符的运用要仔细的观察Text中的这三个需求,注释方便大家更好的去理解。