【学习笔记】 唐大仕—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属性的方法
posted @ 2018-11-10 17:28  cnRicky  阅读(331)  评论(0编辑  收藏  举报