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类型列表