多态
面向对象三大特性:封装、继承、多态
向上造型
1)超类型的引用 Animal ani 指向派生类的对象 new Dog()(即前父后子)
java认为父类大,子类小,所以子类向父类转换类似自动类型转换,称为向上造型
class Animal{}
interface Swim(){}
class Dog extends Animal implements Swim{}
Animal ani = new Dog();//Dog继承于Animal,向上造型
Dog d = new Animal();//编译错误
2)能点出(直接访问)什么,看引用的类型 Animal ani
当对象展现的形态不同,所能拥有的属性和行为也不同,这就是多态
Animal ani = new Dog();//只能点出Animal类中的属性或行为
ani.eat();//只能调用Animal类中的属性和方法
3)可以向上造型成为的类型有:所继承的父类、所实现的接口
Animal ani = new Dog();//向上造型所继承的父类
Swim s = new Dog();//向上造型实现的接口
向上造型的应用场景
-
传参时传入父类,相当于将父类及其子类全部传入,调用该方法时可以new任意子类对象
/** * 主人类,可以喂养动物 */ public class Master { void feed(Animal animal){ //传入Animal父类,传参时可以传Animal类及其子类 animal.eat(); } public static void main(String[] args) { Animal animal01 = new Dog("旺财", 3, "红"); Animal animal02 = new Chick(); Animal animal03 = new Fish(); Master master = new Master(); master.feed(animal01);//喂狗 animal01.eat(); master.feed(animal02);//喂鸡 master.feed(animal03);//喂鱼 } }
-
将父类作为方法返回值类型,可以将方法的返回值扩大到父类及其子类的所有类型
-
扩大引用类型数组范围
定义父类的引用类型数组,其中既可以装父类对象,也可以装其所有子类对象
[!IMPORTANT]
注:此方式不能访问各子类的特有属性和行为
Animal[] animals = new Animal[10]; animals[0] = new Dog();//只能访问Animal中的属性和行为 animals[1] = new Chick(); animals[2] = new Fish();
向下转型
相当于强制类型转换,父类到子类,从大到小
向上转型时父类无法访问子类的属性和行为,若想访问的属性和行为在父类中没有时,须向下转型
若父类中有需要的属性和行为,则不需要转
向下转型成功的条件:
强转时若不满足以下条件,则发生ClassCastException类型转换异常
[!TIP]
强转前通过instanceof判断引用指向的对象是否是该类型,为true则是强转成功的条件
- 引用所指向的对象就是该对象
- 引用所指向的对象实现了该接口或继承了该类
Animal dog = new Dog();
if (dog instanceof Dog){ //true
Dog dog1 = (Dog)dog; //引用dog所指向的对象Dog,就是Dog当前类型
}
if (dog instanceof Swim){ //true
Swim swimDog = (Swim)dog;//引用dog所指向的对象Dog,实现了Swim接口
}
内部类
内部类在编译时也会生成独立的.class字节码文件
成员内部类
类中套类,外面的成为外部类,里面的为内部类
-
内部类通常只服务于外部类,即实例化时只能new外部类,内部类无法在main中实例化(对外不可见)
class Aoo{ void func(){ new Boo;//只能在外部类中访问内部类 } class Boo{ } }
-
内部类中可以直接访问外部类的成员
内部类中有个隐式的引用指向了创建它的外部类对象(外部类名.this)
class Aoo{ int num; class Boo{ System.out.println(num);//内部类直接访问外部类成员变量 System.out.println(Aoo.this.num);//完整写法 } }
匿名内部类
若想创建一个派生类的对象,且对象只创建一次,可以设计为匿名内部类
匿名内部类只能创建一次
创建过程:
-
创建一个Inter的匿名派生类,即创建一个实现了Inter的没有名字的类(不可见)
-
为该派生类创建了一个对象o1,并向上造型为Inter类型
new Inter(){}; 是在创建Inter派生类的对象
{} 中为Inter派生类的类体
public class AnnoInnerClassDemo {
public static void main(String[] args){
Inter o1 = new Inter(){};//匿名内部类
}
}
interface Inter(){
}
匿名内部类的使用
public class AnnoInnerClassDemo {
public static void main(String[] args) {
Inter inter01 = new Inter(){
@Override
public void show() {
System.out.println("show inter01");
}
};
Inter inter02 = new Inter(){
@Override
public void show() {
System.out.println("show inter02");
}
};
inter01.show();
inter02.show();
}
}
interface Inter{
void show();
}
[!IMPORTANT]
注:
- 匿名内部类中不允许修改外部变量的值(main方法中的局部变量),内部类中变量默认带 final 修饰符
- 匿名内部类中是否允许访问外部变量的值,各个jdk版本规定不同