Java多态学习
一、多态的运行:
实例方法:动态绑定,即引用的变量实际引用的类型是哪一个,则运行哪一个实例方法。在运行时由java虚拟机动态决定。
静态方法:静态绑定,即引用的变量所声明的类型是哪一个,则运行哪一个静态方法。在编译阶段就已经做出了决定。
成员变量(包括静态变量和实例变量):静态绑定,即引用变量所声明的类型是哪一个,则运行哪个成员变量。在编译阶段就已经做出了决定。
public class Super {
public String name = "父类名称";//实例变量
public static String age = "父类年龄";//静态变量
public void getName(){
System.out.println("父类实例方法");
}
public static void getAge(){
System.out.println("父类静态方法");
}
}
public class Sub extends Super {
public String name = "子类名称";//实例变量
public static String age = "子类年龄";//静态变量
public void getName(){
System.out.println("子类实例方法");
}
public static void getAge(){
System.out.println("子类静态方法");
}
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.name);//父类的名称
System.out.println(s.age);//父类的年龄
s.getName();//子类的实例方法
s.getAge();//父类的静态方法
}
}
Super s = new Sub();
引用变量所声明的类型 : Super
引用的变量实际引用的类型 :Sub
二、多态的分类
多态一般分为两种:重写式多态和重载式多态。重写和重载这两个知识点前面的文章已经详细将结果了,这里就不多说了。
重载式多态,也叫编译时多态。也就是说这种多态再编译时已经确定好了。重载大家都知道,方法名相同而参数列表不同的一组方法就是重载。在调用这种重载的方法时,通过传入不同的参数最后得到不同的结果。
重写式多态,也叫运行时多态。这种多态通过动态绑定(dynamic binding)技术来实现,是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。也就是说,只有程序运行起来,你才知道调用的是哪个子类的方法。
这种多态通过函数的重写以及向上转型来实现,我们上面代码中的例子就是一个完整的重写式多态。我们接下来讲的所有多态都是重写式多态,因为它才是面向对象编程中真正的多态。
二、父类类型的引用不能获取子类非继承的方法
三、当子类没有重写父类的方法,则会调用父类的方法
public class Super {
public void getName(){
System.out.println("父类实例方法");
}
public void getAge(){
System.out.println("父类静态方法");
}
}
public class Sub extends Super {
public void getAge(){
System.out.println("子类静态方法");
}
public static void main(String[] args) {
Super s = new Sub();
s.getName();//子类没有重写父类的方法getName(),所以调用的是父类的方法 父类的实例方法
s.getAge();//子类的实例方法
}
}
四、继承链中对象方法的调用的优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
class C extends B{
}
class D extends B{
}
public class Demo {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
}
}
//结果:
//1--A and A
//2--A and A
//3--A and D
//4--B and A
//5--B and A
//6--A and D
//7--B and B
//8--B and B
//9--A and D
分析:4
首先,a2是类型为A的引用类型,它指向类型为B的对象。A确定可调用的方法:show(D obj)和show(A obj)。
a2.show(b) ==> this.show(b),这里this指的是B。 然后.在B类中找show(B
obj),找到了,可惜没用,因为show(B
obj)方法不在可调用范围内,this.show(O)失败,进入下一级别:super.show(O),super指的是A。 在A
中寻找show(B obj),失败,因为没用定义这个方法。进入第三级别:this.show((super)O),this指的是B。
在B中找show((A)O),找到了:show(A obj),选择调用该方法。 输出 B and A
参考博客: https://wj196.iteye.com/blog/1323244
https://blog.csdn.net/qq_38071429/article/details/85010402
http://blog.csdn.net/qq_31655965/article/details/54746235