【学习笔记】 唐大仕—Java程序设计 第5讲 深入理解Java语言之5.3 对象构造与初始化
对象构造与初始化
构造方法
-
构造方法(constructor)
- 对象都有构造方法
- 如果没有,编译器加一个default构造方法
-
抽象类(abstract)有没有构造方法?
- 答案:抽象类也有构造方法。实际上,任何类都有自己的构造方法
调用本类或父类的构造方法
-
调用本类或父类的构造方法
- this调用本类的其他构造方法
- super调用父类的构造方法
- this和super要放在第一条语句,且只能够有一条
-
如果没有this及super,则编译器自动加上super(),即调用直接父类不带参数的构造方法
-
因为必须令所有父类的构造方法都得到调用,否则整个对象的构建就可能不正确
创建对象时初始化
- p = new Person(){{ age = 18; name = "李明" }}
- 这样可以针对没有相应构造函数,但又要赋值的情况
- 注意双括号
实例初始化与静态初始化
-
实例初始化(Instance Initializers)
-
在类中直接写
- { 语句.... }
- 实例初始化,先于构造方法{}中的语句执行
-
静态初始化(Static Initializers)
- static{ 语句.... }
- 静态初始化,在第一次使用这个类时要执行
- 但其执行的具体时机是不确定的
- 但是可以肯定的是:总是先于实例的初始化
构造方法的执行过程
-
构造方法的执行过程遵照以下步骤:
- 调用本类或父类的构造方法,直至最高一层(Object)
- 按照声明顺序执行字段的初始化赋值
- 执行构造函数中的各语句
-
简单的说:
- 先父类构造,再本类成员赋值,最后执行构造方法中的语句
一个问题
- 构造方法内部调用别的方法
- 如果这个方法是虚方法(不是用private,private,final修饰的方法),结果如何?
- 从语法上来说这是合法的,但有时会造成事实上的不合理
class ConstructInvokeMetamorph { public static void main(String[] args){ Person p = new Student("李明", 18, "北大"); } } class Person { String name="未命名"; int age=-1; Person( String name, int age ){ this.name=name; this.age=age; sayHello(); } void sayHello(){ System.out.println( "我是一个人,我名叫:" + name + ",年龄为:"+ age ); } } class Student extends Person { String school="未定学校"; Student( String name, int age, String school ){ super( name, age ); this.school = school; } void sayHello(){ System.out.println( "我是学生,我名叫:" + name + ",年龄为:"+ age + ",学校在:" + school ); } }
- 在本例中,在构造函数中调用了一个动态绑定的方法sayHello(),这时,会使用哪个方法被覆盖的定义,而这时对象还没有完全构建好,所以,School还没有赋值
- 因此,可能的话,在构建器中避免调用任何方法,用尽可能简单的方法使对象进入就绪状态
- 唯一能够安全调用的是具有final属性的方法