Java多态遇到泛型类型

来源:互联网 发布:cnki期刊数据库 编辑:程序博客网 时间:2024/05/16 19:21

1.数组参数的多态化

(1):实例1

class Animal{void eat(){System.out.println("animal is sleeping");}}class Dog extends Animal{void bark(){System.out.println("dog is barking");}}class Cat extends Animal{void meow(){System.out.println("cat is meowing");}}class HelloWorld{public static void main(String[] args){Animal[] animals = {new Dog(),new Dog(),new Dog()};takingAnimals(animals);}public static void takingAnimals(Animal[] animals){animals[0] = new Cat();}}

编译和运行都可以通过


(2)实例2:

class Animal{void eat(){System.out.println("animal is sleeping");}}class Dog extends Animal{void bark(){System.out.println("dog is barking");}}class Cat extends Animal{void meow(){System.out.println("cat is meowing");}}class HelloWorld{public static void main(String[] args){Dog[] dogs = {new Dog(),new Dog()};takingAnimals(dogs);}public static void takingAnimals(Animal[] animals){animals[0] = new Cat();}}
编译的时候不会出错,但运行的时候会出错,这是因为数组类型是在运行期间检查的,运行期间检查到animlas[0]是Dog类型,将Cat类型的实例赋给它,会报错


2.将上面的数组array换成列表ArrayList时:

集合参数的多态化:

(1)实例1:

class Animal{void eat(){System.out.println("animal is sleeping");}}class Dog extends Animal{void bark(){System.out.println("dog is barking");}}class HelloWorld{public static void main(String[] args){ArrayList<Animal> animals = new ArrayList<Animal>();animals.add(new Dog());animals.add(new Dog());takingAnimal(animals);}public static void takingAnimal(ArrayList<Animal> animals){for(Animal a:animals){a.eat();}}}
编译可以通过,运行也可以通过


(2)实例2:

如果传入takingAnimal方法的是Dog类型的列表

class Animal{void eat(){System.out.println("animal is sleeping");}}class Dog extends Animal{void bark(){System.out.println("dog is barking");}}class HelloWorld{public static void main(String[] args){ArrayList<Dog> dogs = new ArrayList<Dog>();dogs.add(new Dog());dogs.add(new Dog());takingAnimal(dogs);}public static void takingAnimal(ArrayList<Animal> animals){for(Animal a:animals){a.eat();}}}

      编译器无法通过,编译器不让通过是为了避免下面的情况,若传入 takeAnimals方法的是Dog类型的列表dogs,这时无法将一只猫添加进dogs列表中,为什么上面的数组可以编译通过呢,这是因为数组的类型是在运行期间检查的,而集合的类型检查只会 发生在编译期间

public void takeAnimals(ArrayList<Animal> animals){animals.add(new Cat());}


3.多态化集合参数的办法 :有一种能够创建出接收Animal子型参数的方法,就是使用万用字符,万字符有两种语法形式

 第一种语法:

public static void takingAnimal(ArrayList<? extends Animal> animals){for(Animal a: animals){a.eat();}}
第二种语法:

public static<T extends Animal> void takingAnimal(ArrayList<T> animals){for(Animal a: animals){a.eat();}}

     使用万用符的好处:传入takingAnimal方法的可能还是dogs列表,这样dogs列表里面还是可能被加进去Cat类型的实例,但实际上使用带有<?>的声明时,编译器不会允许加入任何东西到集合中。 


4.两者的对比

public static void takingAnimal(ArrayList<Animal> animals)
与public static void takingAnimal(ArrayList<? extends Animal> animals)的对比

 <? extends Animal>表示任何Animal和Animal的子型都是合法的,可以输入ArrayList<Dog>,ArrayList<Cat>,ArrayList<Animal>类型的参数

ArrayList<Animal> animals 表示只有ArrayList<Animal>类型是合法的


5.练习:

ArrayList<Dog> dog1 = new ArrayList<Animal>();
错误  说明:这个都不是多态,显然错误

ArrayList<Animal> animals = new ArrayList<Dog>();
错误  说明:正如上面分析的,集合的类型检查会在编译期间,编译器不会允许这种形式的多态,将一个Dog类型的列表赋给Animal类型列表

List<Animal> animals = new ArrayList<Animal>();
正确 说明:ArrayList实现了List接口

ArrayList<Dog> dogs = new ArrayList<Dog>();
正确 说明:声明了一个Dog类型的列表dogs

ArrayList<Animal> animals = dogs;
错误 说明:正如上面分析的,集合的类型检查会在编译期间,编译器不会允许这种形式的多态,将一个Dog类型的列表赋给Animal类型列表




原创粉丝点击