一、继承体系中的初始化顺序
当我们使用new创建一个对象的时候,这个对象会在类的继承体系中按以下顺序执行初始化:
- 初始化父类的静态变量和静态代码块,按它们在代码中定义的顺序执行(先定义先执行);
- 初始化子类的静态变量和静态代码块,按它们在代码中定义的顺序执行(先定义先执行);
- 初始化父类的实例变量和实例代码块,按它们在代码中定义的顺序执行(先定义先执行);
- 执行父类的构造方法;
- 初始化子类的实例变量和实例代码块,按它们在代码中定义的顺序执行(先定义先执行);
- 执行子类的构造方法。
当该类存在多层次的继承体系时,则按以上顺序递归地执行初始化。
/** * 父类 */ class SuperClass { //父类的静态代码块 static { System.out.println("Initalizing static block in SuperClass\n"); } //父类的实例代码块 { System.out.println("Initalizing instance block in SuperClass\n"); } //父类的静态变量 public static Var StaticSuperVar = new Var("static variable in SuperClass"); //父类的实例代变量 public Var superVar = new Var("variable in SuperClass"); //父类的构造方法 public SuperClass() { System.out.println("Initalizing SuperClass\n"); } } /** * 子类 */ class SubClass extends SuperClass { //子类的静态变量 public static Var StaticSubVar = new Var("static variable in SubClass"); //子类的实例变量 public Var subVar = new Var("variable in SubClass"); //子类的静态代码块 static { System.out.println("Initalizing static block in SubClass\n"); } //子类的实例代码块 { System.out.println("Initalizing instance block in SubClass\n"); } //子类的构造方法 public SubClass() { System.out.println("Initalizing SubClass\n"); } } /** * 辅助类 */ class Var { public Var(String name) { System.out.println("Initalizing " + name + "\n"); } } /** * 测试类 */ public class InitOrderTest { public static void main(String[] args) { SubClass subClass = new SubClass(); } }
运行结果:
Initalizing static block in SuperClass Initalizing static variable in SuperClass Initalizing static variable in SubClass Initalizing static block in SubClass Initalizing instance block in SuperClass Initalizing variable in SuperClass Initalizing SuperClass Initalizing variable in SubClass Initalizing instance block in SubClass Initalizing SubClass
二、多态中的属性
在Java中,只有方法调用是多态的,而属性访问是在编译器解析的。表面上看是子类重写了父类的某个属性,实际上是子类获得了两个同名的属性,使用父类引用访问的属性是父类的属性,而子类引用则默认访问子类的属性,要访问父类属性则必须显式用super。
class SuperClass { public int field = 0; public int getField() { return field; } } class SubClass extends SuperClass { public int field = 1; public int getField() { return field; } public int getSuperField() { return super.field; } } public class FieldTest { public static void main(String[] args) { SuperClass sup = new SubClass(); System.out.println("sup.field = " + sup.field + ", sup.getField() = " + sup.getField()); System.out.println(); SubClass sub = new SubClass(); System.out.println("sub.field = " + sub.field + ", sub.getField() = " + sub.getField()); System.out.println("sub.getSuperField() = " + sub.getSuperField()); } }
结果
sup.field = 0, sup.getField() = 1 sub.field = 1, sub.getField() = 1 sub.getSuperField() = 0
三、私有方法与静态方法
当子类拥有与父类的某个私有方法相同签名的方法时,表面上是子类重写了父类的私有方法,实际上因为私有方法是隐式设成final的,而且对子类是屏蔽的,所以这种情况下是子类定义了新的方法,而不存在重载。
class SuperClass { private void privateFunc(){ System.out.println("SuperClass"); } public static void main(String[] args) { SuperClass sup = new SubClass(); sup.privateFunc(); } } class SubClass extends SuperClass { private void privateFunc(){ System.out.println("SubClass"); } }
结果
SuperClass
静态方法也不具有多态性,因为静态方法是与类而不是对象相关联的。
class SuperClass { public static void func(){ System.out.println("SuperClass"); } } class SubClass extends SuperClass { public static void func(){ System.out.println("SubClass"); } } public class FieldTest { public static void main(String[] args) { SuperClass sup = new SubClass(); sup.func(); } }
结果:
SuperClass
四、方法签名冲突
当同时实现多个接口或者同时实现接口与继承某个父类时,如果在这些被实现的接口和被继承的父类中存在签名相同但返回类型不相同的方法时,会出现冲突并造成编译错误。
interface Interface{ public void func(); public void anotherFunc(); } interface AnotherInterface{ public int func(); } class SuperClass{ public int anotherFunc(){ return 0; } } class SubClass extends SuperClass implements Interface, AnotherInterface{ @Override public void func() { //方法编译错误: //‘func()' in 'SubClass' clashes with 'func()' in AnotherInterface; // attempting to use incompatible return type } @Override public void anotherFunc() { //方法编译错误: //‘anotherFunc()' in 'SubClass' clashes with 'anotherFunc()' in SuperClass; // attempting to use incompatible return type } }
五、变量冲突
与方法签名冲突类似,同名的属性(变量)也会出现冲突。
interface Interface { String FIELD = "Interface"; } class SuperClass { public String FIELD = "SuperClass"; } class SubClass extends SuperClass implements Interface { } public class FieldConflictTest { public static void main(String[] args) { SubClass cls = new SubClass(); //编译错误: //Reference to 'FIELD' is ambiguous, //both 'SuperClass.FIELD' and 'Interface.FIELD' match System.out.println(cls.FIELD); } }
相关推荐
代码演示对java中多态的理解 从代码演示中更好的理解多态的作用
想要下载此文件,请先下载本人“java程序中的内存分配问题”,因为那个例子比较简单而且分析详细透彻,可以使你更容易理解,如果你对java程序执行过程中的内存分配有一定的了解,可以直接下载本文件
深入Java核心 Java中多态的实现机制
java多态、继承练习题,包含题目与答案,............................................................................................................
java多态实现的课件,给那些需要的人 讲述了java多态的概念、分类、实现 综合案例讲解、总结多态的作用
Java多态的讲解
Java开发之多态的具体应用,包含多态应用的实例和相应实例的代码。
java的多态,是一个很重要的环节.但是要知道什么是多态!
深入Java核心 Java中多态的实现机制.docx
深入Java核心Java中多态的实现机制.pdf
Java 多态中的类型转换
JAVA多态思维导图,便捷整理思路,多态的好处、多态的语法格式、多态中的两种类型转换:向上转型、向下转型
利用大量代码讲解java的多态,让你更容易理解和应用。
北大青鸟javaOOP多态Ch03作业全集.rar
Java基础多态PPT教学课件.pptx
java 继承和多态PPT教程
java教学视频,讲解了多态的扩展性、转型、成员特点、主板实例、object类等