Java泛型浅谈(2)

来源:互联网 发布:生死狙击刷矩阵要多久 编辑:程序博客网 时间:2024/05/16 05:08

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

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

定义方式: <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
原创粉丝点击