JAVA 多态(以及多态在数组和ArrayList中的体现)

来源:互联网 发布:青蜂网络 编辑:程序博客网 时间:2024/06/11 03:37
多态意味着,你可以把一个dog,当做一个Dog,或者Animal,或者一个Object

Animal a=new Dog();

新建一个Dog类型的对象,用一个Animal的引用来指向它
但是我们不能用a.bark(),因为Animal类中没有bark()方法.
换言之,Animal类型的引用a就像一个遥控器,没有bark()功能的键)

需要强制类型转化:
Dog b=(Dog) a;
b.bark();

引用,参数,返回值都可以是多态的


多态在数组和ArrayList上的表现:
①各子类的实例能同时存放在父类类型的数组中
如:Animal[ ] animals=(new Dog(),new Cat(),new Rabbit);
//Dog Cat Rabbit 都是Animal的子类

②对于每个数组元素调用方法:
在这边举一个例子:
这是定义的三个类:(Animal Dog Cat里面都有方法eat())
JAVA 数组 多态 - 小镜子~ - 菜园子
声明:
Dog d=new Dog();
Cat c=new Cat(); 
Animal[ ] animals={d,c};
对每个Animal[ ]中的元素调用eat():
JAVA 数组 多态 - 小镜子~ - 菜园子
  结果显示,调用的是Dog和Cat各自的eat(),而非Animal的eat():
JAVA 数组 多态 - 小镜子~ - 菜园子
但是如果Animal中没有eat();
(把Animal中的eat()方法注释掉)
编译器会报错:(需要强制类型转化Animal--->Dog)
(不免让人想起很多的以前的例子,强制类型转化来调用父类所没有的功能)
JAVA 数组 多态 - 小镜子~ - 菜园子
③ArrayList<T> 的多态
.基本跟Array数组是一样的
不一样的地方:
JAVA 数组 多态 - 小镜子~ - 菜园子
这样的以ArrayList<Animal>为参数类型的方法,不能传入ArrayList<Dog> 这样的参数
//Dog extends Animal
(如果参数类型是Animal[ ] 那么可以传入Dog[ ])
为什么会这样呢?

①为什么ArrayList不行:
因为如果写了这样一个方法:
JAVA 数组 多态 - 小镜子~ - 菜园子
而传入的是一个ArrayList<Dog>,那就会在狗群里面混入一只猫,这是编译器不允许的
②为什么数组行
因为数组的类型是在运行期间检查(JAVA虚拟机来报错),但集合的类型检查只会发生编译期间(编译器来报错)

③解决方案
public void takeThing(ArrayList<? extends Animal> list){}
或者
public <T extends Animal> void takeThing(ArrayList<T> list){}
二者是等价的
详见java 泛型:http://blog.163.com/it_novice/blog/static/20918306920133885429926/

解决问题的原因:add(new Cat())这类方法直接不被允许了,编译器会禁止向集合添加对象。
这样一来,就能传入很多子类型的ArrayList了

 
④下图要表达的意思:
JAVA 数组 多态 - 小镜子~ - 菜园子
   可以说狗是动物,但不能说动物是狗
   ArrayList前后都要一样