This constructor runs when you construct objects of the Employee class—giving the instance fields the initial state you want them to have.
public Employee(String n, double s, int year, int month, int day) {
name = n;
salary = s;
hireDay = LocalDate.of(year, month, day);
}
A constructor can only be called in conjunction with the new
operator. (就是注意,C++ 那一套别用进来)
看起来,好像没有 C++ 中那套 list initialize
About null
null
仅代表 obj 的缺席,并不适合作为未知数据的替代,对 null
的 invoke 会导致严重问题,所以我们
The “permissive” approach is to turn a null
argument into an appropriate non-null
value:
if (n == null) name = "unknown"; else name = n;
name = Objects.requireNonNullElse(n, "unknown");
The “tough love” approach is to reject a null
argument:
Objects.requireNonNull(n, "The name cannot be null");
name = n;
Parameter Names code-style
当我们有的时候写 constructor 的时候,对 para 的命名会是一个比较头疼的过程 (就像给 class 命名一样),所以提供几个可参考的方案使用
// 1. 直接用字母。方便,但是可读性不好 public Employee(String n, double s) { name = n; salary = s; } // 2. 前缀“a”。不错 public Employee(String aName, double aSalary) { name = aName; salary = aSalary; } // 3. 利用 hide 特性。也可以 public Employee(String name, double salary) { this.name = name; this.salary = salary; }
C++ 中通常会对 field 加一个前缀字符,比如:
_salary
,mSalary
,xSalary
但 Java 通常不这么干
我也不造这么不错的方法干嘛不用
Default Field Initialization
跟 C++ 一样,当没有指明的时候,有一个默认的初值,对于数字是 0
,布尔是 false
,类是 null
但也一样的,不希望这么用,要是对 null
invoke method 就不好了
No-Argument Constructor
前面的那都是纯语言级的 default,我们通常会用的 default 还是自己定义的,不提供参数的构造函数
When the Default Constructor Valid
跟 C++ 很像,当我们确实是什么都没提供的时候,语言级会给我们生成一个
但是当我们自己构造了一个的时候,就不会给我们自己生成了
Explicit Field Initialization
就是给 instance fields 来一个内部的 initial state (field initializers/in-class initializers)
⚠️ 并非一定要是 constant value,也可以是一个 method
⚠️ 并且调用构造函数的时候,还是先运行 in-class initializers
Calling Another Constructor
如果在当前的构造函数里第一句话是 this(...)
那就是 call another constructor 了
public Employee(double s) {
// calls Employee(String, double)
this("Employee #" + nextId, s);
nextId++;
}
vs. Delegating Constructors in C++
书中说:“However, in C++ it is not possible for one constructor to call another.”这个要怎么看呢
我想是这样的,因为 C++ 有 initializer list 的机制,在 construct 中它区分 initial 和 assign,当运行到 block 中是,构造已经结束了
而 Java 不是这样的,经验证,block 中也可 “assign” to constant
Initialization Blocks
第三种方法来初始化,就是只是在 class 中加入一个 block {...}
。blocks 里直接用变量名字就可以了
当构造函数被调用的时候,它运行在构造函数 body 之前 (换句话说,如果没有构造函数被调用,就不会运行 initialization blocks。而且后面会说,static
blocks behave differently)
⚠️ 另外,它允许 set 那些尚未出现的 fields,但是不允许在 block 中调用它
Static Initialization Blocks
对 block 加上 static
修饰即可
Static initialization occurs when the class is first loaded.
介绍了这么多的构造的方法,但到底当一个构造方法被 invoke 的时候,发生了怎样的过程
- 先看看第一行是不是在叫别的构造方法,如果是,那就去执行别的构造方法
- 否则的话
- 语言级给一个 default 值
- field initializers 和 initialization blocks 按照 class declaration 中出现的顺序依次执行
- 最终才是把整个构造方法的 body 执行了
一级标题
二级
加粗,加斜