Java泛型浅谈(2)

五、泛型参数的界限(通配符)

20220328 补充:Java中<? extends T>和<? super T>的理解# - chenxibobo - 博客园 (cnblogs.com)

不能往里存,只能往外取

泛型类或者接口中,拥有“不确定的”类型. 但是,我们也可以限定其为“某一部分类型”, 即为某个类的子类。

定义方式: <T extends BoundingType> ,   T 和 BoundingType 既可以是类,也可以是接口。

那么SimpleClass <BoudingType> 就是 SimpleClass <T> 的父类呢? 其中SimpleClass 是表示一个自定义的类名,通过一个小程序来看看:

public class GenericeTest03 {

	public static void main (String[] args) {
		
		Information <Integer> age1 = new Information <Integer> (10);
		Information <Number> age2;
		age2 = age1; // (1)
	}
}


class Information<T> {
	private T data;
	
	public Information() {
	}
	
	public Information(T data) {
		this.data = data;
	}
	
	public T getData(){
		return data;
	}
	
	public void setData(T data) {
		this.data = data;
	}
}

编译出错:

Exception in thread "main" java.lang.Error: Unresolved compilation problem:  Type mismatch: cannot convert from Information<Integer> to Information<Number> at GenericeTest03.main(GenericeTest03.java:8)

由此可以看出, 虽然 Number 类 是Integer类的父类, 但是 Information <Number> 却不是 Information <Integer> 的父类.

实际上 Information <Integer extends Number>,  即可以限定泛型的类型是在某些范围内的, 以确保类型安全.

那有没有存在同时是 Information<Number> 和Information<Integer>的父类,使得程序更加通用? 那就是使用类型通配符 <?>

public class GenericeTest03 {

	public static void main (String[] args) {
		
		Information <Integer> age1 = new Information <Integer> (10);
		Information <Number> age2 = new Information <Number> (11); // new
		//age2 = age1; // (1)
		
		Information <? extends Number> age3; // (2)
		age3 = age1; // (3)
		System.out.println("age3.getData() = " + age3.getData());
		age3 = age2; // (4)
		System.out.println("age3.getData() = " + age3.getData());
	}
}


class Information<T> {
	private T data;
	
	public Information() {
	}
	
	public Information(T data) {
		this.data = data;
	}
	
	public T getData(){
		return data;
	}
	
	public void setData(T data) {
		this.data = data;
	}
}

运行结果:

parent.getData() = 10
parent.getData() = 11

(3) 处定义了age3, 使用了类型通配符 < ? extends Number>, 因此,其把 age1 和age2的值赋给它.

即可得出结论: <? extends Number> 是 <Integer> 和 <Number> 的父类.

其中 <? extends Number> 这种称为类型通配符上限,相应的 <? super Number> 称为类型通配符下限。

此外,另个一例子可以更好地理解泛型通配符, 参考:  http://www.linuxidc.com/Linux/2013-10/90928.htm

类图很简单, 直接上代码

public class Animal {

	private String name;
	
	public Animal(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	
	public void eat() {
        System.out.println(getName() + " can eat.");
	}
}
public class Bird extends Animal {

	public Bird(String name) {
		super(name);
	}

	public void fly() {
		System.out.println(getName() + " can fly.");
	}
}

public class Cat extends Animal {

	public Cat(String name) {
		super(name);
	}
	
	public void jump() {
		System.out.println(getName() + " can jump.");
	}

}
public class Magpie extends Bird {

	public Magpie(String name) {
		super(name);
	}
	
	public void sing() {
		System.out.println(getName() + " can not only eat, but sing");
	}

}

import java.util.List;

public class AnimalTrainer {
/*
	public void act (List<Animal> list) {
		for (Animal animal : list) {
			animal.eat();
		}
	}*/

	public void act (List<? extends Animal> list) {  // 具体类型由调用时确定 // public <T extends Animal> act (List <T> list)
		for (Animal t: list) {
			t.eat();
		}
	}
}
import java.util.ArrayList;
import java.util.List;

public class TestAnimal {

	public static void main (String[] args) {
		AnimalTrainer animalTrainer = new AnimalTrainer();
		
		List<Animal> animalList = new ArrayList<>();
		animalList.add(new Cat("cat1"));
		animalList.add(new Bird("bird1"));		
		animalTrainer.act(animalList);
		
		List<Bird> birdList = new ArrayList<>();
		birdList.add(new Bird("bird2"));
		birdList.add(new Bird("bird3"));
		animalTrainer.act(birdList);
		
		List<Cat> catList = new ArrayList<>();
		catList.add(new Cat("cat2"));
		catList.add(new Cat("cat3"));
		animalTrainer.act(catList);
		
	}
}

重要的是AnimalTrainer的 act()方法中,定义的泛型参数列表, 能接收来自catList / birdList 的类型。 如果是 void act (List <Animal> list) , 则如果往其加入cat , 则会报错.




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值