多态:在同一个时刻体现出来的不同状态;
多态的前提:
1) 必须有继承关系;
子类继承父类,存在一些特点;
2) 必须有方法重写;
子类继承父类,方法重写的目的,举例:动物吃的方法,每一个具体动物吃的东西不一样,所有必须要方法覆盖;
3) 就是必须有父类的引用指向子类对象 ==> (向上转型);
父类名 fu = new 子类名( ) ;
父类对象的创建是通过子类在堆内存新建了一个对象,由于子类又继承了父类,父类的引用(初始化)
是通过子类新建对象进行的;
多态中的成员访问特点:
1)成员变量: 编译看左,运行看左;
2)成员方法(非静态): 编译看左,运行看右(存在方法重写);
3)构造方法: 构造方法(无论子类,还是父类),都是对对象进行初始化;
4)静态成员方法: 编译看左,运行看左(静态跟类有关系,算不上方法重写);
举例:
class Fu{
int num = 20 ;
public void show() {
System.out.println("show Fu....");
}
public Fu(){
}
public static void function() {
System.out.println("function Fu...");
}
}
//子类
class Zi extends Fu{
int num = 30 ;
public void show() {
System.out.println("show Zi....");
}
public static void function() {
System.out.println("function Zi...");
}
public void method() {
System.out.println("----4");
}
}
//测试类
public class DuoTaiDemo {
public static void main(String[] args) {
//创建父类对象,通过子类创建对象
Fu f = new Zi() ; //向上转型;
System.out.println(f.num); //多态中访问成员变量:编译看父类,运行看父类 ==> 所以输出父类的成员变量num;
f.show(); //多态中访问成员方法(非静态):编译看父类,运行看子类 ==> 所以执行子类的show方法;
f.function(); //多态中访问静态成员方法:编译看父类,运行看父类(静态跟类有关系,算不上方法重写);
//f.method() ; //会报错,因为多态的前提之一有方法重写,而method()这个方法没有方法重写,所以会报错;
}
}
多态的好处:可以提供代码的复用性:继承保证;
可以提高的代码的扩展性:由多态保证 (父类的引用指向子类对象);
多态的弊端:
父类引用指向子类对象,通过父类的引用调用子类特有功能,不能调用;
例如:上面例题中的method()方法,父类 f 不能调用;
问题:
可不可以将子类的引用指向父类的引用呢? (向下转型)
解决方法:
将父类的引用强制转换成子类的引用;
//以上述代码举例:
//创建父类对象,通过子类创建;
Fu f = new Zi(); //向上转型;
Zi z = (Zi) f; //前提是必须有父类的引用,有了向上转型,才能创建向下转型;
z.method(); //通过子类对象z访问method()方法;
分层初始化:看程序,写结果: 爱你
//代码分析:
//进入main方法,先通过类B创建类A的引用,接着访问父类的show()方法,执行其中的语句,根据多态中成员访问特点,访问成员方法,编译看父类,运行看子类;
//所以会执行子类的show2()方法,执行其中的语句,输出==> 爱;
//执行完,返回main方法,接着通过类C创建类B的引用,接着访问show()方法,因为类A,B,C形成了分层继承,所以在类B中隐式的存在类A方法名为show()的方法;
//所以,访问类C中的show方法,执行其中的语句,接着访问类B中的show()方法,执行其中的语句;
//在多态中访问成员的特点,访问成员方法,编译看父类,运行看子类,所以执行子类中的shoe2()方法,执行其中的语句,输出 ==> 你;
//所以输出的结果为 : 爱你
class A {
public void show() {
show2();
}
public void show2() {
System.out.print("我");
}
}
class B extends A {
/**
* 解决问题的关键:类B继承了类A,所以会隐式的存在方法名为show()方法;
* public void show(){
* show2() ;
* }
*/
public void show2() {
System.out.print("爱"); //爱
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.print("你");// 你
}
}
public class DuoTaiTest {
public static void main(String[] args) {
A a = new B();
a.show();
B b = new C();
b.show();
}
}
两个面试题:
1、overload和override的区别?
overload:方法重载
方法名一样,参数不同,和返回值没有关系
参数不同:
1)参数个数不同
2)参数类型不同
override:方法重写 (子类定义一个和父类一摸一样的方法声明)
继续中使用到的
2 关于this和super的区别?
this:代表当前类的对象
super:代表父类空间标识,理解为代表父类的对象
应用场景:
成员变量
this.成员变量
super.成员变量
成员方法
this.成员方法()
super.成员方法();
构造方法
this()/this("..")
super()/super("...");