Java中匿名内部类的多态特性探讨
多态是面向对象的三大特性之一,所谓多态,大致理解起来就是说大千世界中的对象在不同的环境下可能会有多种形态。比如一个动物,即可能是猫,也可能是狗;而猫和狗也都是动物。
Java中多态存在的前提:
- 必须存在继承。
- 父类的引用指向子类的对象
一般形式的多态
public class Animal {
public void eat(){
System.out.println("Animal需要吃");
}
public void sleep(){
System.out.println("Animal需要睡觉");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫正在吃鱼");
}
@Override
public void sleep() {
System.out.println("猫白天睡觉");
}
public void miaow(){
System.out.println("猫正在喵喵叫");
}
}
Cat继承Animal,并且有一个新方法:miaow(),喵喵叫。Animal的属性和行为,Cat都是有的。但具体表现可能不一样,就sleep()方法而言,并不是所有的Animal都是白天睡觉,所以就存在方法的覆盖。Cat还有特有的行为:喵喵叫。这个行为不是所有的Animal都具备的。
一个典型的多态的例子是:
Animal animal=new Cat();
animal.sleep();
运行结果是:猫白天睡觉
因为父类的引用指向了子类的对象,所以执行的是子类的方法。
Animal animal2=new Cat();
animal2.miaow();
编译失败,Animal中不存在miaow()方法,Cat没有实现方法的覆盖,不属于多态。
一句话,多态中,父类的引用只能使用子类已经覆盖的方法,不能使用子类特有的方法。
这种多态的形式很常见,比如通过List list=new ArrarList()建立ArrarList对象。
匿名内部类中的多态
1,普通类的多态
public class Animal {
//普通的类
public void eat(){
System.out.println("Animal需要吃");
}
public void sleep(){
System.out.println("Animal需要睡觉");
}
}
/**多态,new Animal()其实是子类的对象,animal是父类的引用。子类重写父类的方法
实现多态。android中的Handler也是这种多态的表现形式。new一个对象后面再重写方法,那么这个对象必然是子类对象。*/
Animal animal=new Animal(){
@Override
public void eat() {
System.out.println("子类对象正在吃");
}
@Override
public void sleep() {
System.out.println("子类对象正在睡觉");
}
};
animal.eat();
animal.sleep();
执行结果:
子类对象正在吃
子类对象正在睡觉
new Animal()其实是子类的对象,animal是父类的引用。子类重写父类的方法,是多态的体现
2,抽象类的多态
public abstract class Person {
abstract void run();
abstract void think();
abstract void useTools();
}
public static void useAbstract(){
Person person=new Person() {
@Override
void useTools() {
System.out.println("人会使用工具");
}
@Override
void think() {
System.out.println("人会思考");
}
@Override
void run() {
System.out.println("人会奔跑");
}
};
person.think();
}
执行结果:输出“人会思考”。
抽象类是不能实例化的,new Person()只是Person的一个子类对象,而非Person的对象。这个子类必须重写Person所有的抽象方法。
父类引用指向子类对象,也是多态的体现。
3,接口的多态
public interface ClickLisenter {
public abstract void click();
}
public static void testDuotai(){
/**
* 接口的多态:
* 接口是不能实例化的,new ClickLisenter()其实是实现ClickLisenter的子类。
* 父类的引用指向子类对象,子类覆盖父类的方法(接口的引用指向实现它的对象,该对象重写接口的抽象方法);
*/
ClickLisenter clickLisenter= new ClickLisenter(){
@Override
public void click() {
System.out.println("点击");
}
};
clickLisenter.click();
}
执行结果:输出“点击”
和抽象类一样,接口也不能实例化。new ClickLisenter()其实是实现ClickLisenter的类对象,可以将其看作“子类”。
接口的引用指向实现他的子类对象,覆盖抽象方法,是多态。
接口这种形式的匿名对象实现多态非常常见,比如java GUI和android中的各种点击事件。回调等。