构造方法 constructor
构造实例的方法。
构造方法的定义
构造方法的方法名必须与类名一样,而且构造方法没有返回值。这样的方法才是构造方法。
// 构造方法没有返回值(连 void 都没有),而别的方法没有返回值的时候还得写个 void。
public Testclass(){
xxx;
}
构造方法可以有参数,规则和语法与普通方法一样。使用时,参数传递给 new 语句后类名的括号后面。
如果没有显式地添加一个构造方法,java 就会为每个类都默认添加一个无参数的构造方法。
如果我们自己添加类的带参数构造方法,java 就不会再添加无参数的构造方法。这时,就不能直接 new 一个对象而不传递参数了。
- 即是说,你如果想着只要不添加无参数构造方法,而添加有参数构造方法,就能和 java 自己本来默认添加的无参数构造方法形成方法重载,那么你就要失望了,java 不会因为自动添加的构造方法的方法签名不同,直接给你隐式重载了。只要你手动编写了构造方法,java就不会隐式自动添加无参数构造方法。
如果我们自己添加类的构造方法也是无参的,即便方法体内什么都不写,还是不会影响对象的创建,只是如果方法体里面有代码逻辑,就会在创建对象的同时,执行这些代码,完成相关操作。
构造方法的调用
构造方法无法被点操作调用,也无法在普通方法里调用,只能通过 new 语句在创建对象的时候,间接调用(或在重载的构造方法中调用,详细见下一节)。
- 为什么构造方法没有返回值?因为有返回值也没有意义。new 语句永远返回的是创建出来的的对象的引用。
构造方法的重载
在构造方法里才能调用重载的构造方法。语法:
this(实参列表);
-
构造方法不能自己调用自己,因为这样是一个死循环。
-
在调用构造方法时,不可使用成员变量(指参数中使用成员变量,而非在构造方法方法体内使用成员变量)。因为从语意上讲,这个对象还没被初始化完成,处于中间状态。
-
在构造方法里调用重载的构造方法(
this(参数列表)
)时,必须将调用写在方法体的第一行,后面可以继续有代码。
public class Person{
public String id;
public int count = 10; // 构造方法执行前,会执行给成员变量赋初始值的操作
public Person(){
this("Tom",13);
}
public Person(String name,int age){
this(name,age,40);
System.out.println("玩家默认体重:40");
}
public Person(String name,int age,double weight){
xxxx;
}
}
在构造方法执行前,java 就会执行给成员变量赋初始值的操作。(因此并非一定将成员变量的赋值操作放到构造方法中)
疑问1:java 的所有代码都必须在方法里,那么类里面对成员变量的声明与赋初始值看起来好像并不在某个方法体内呀?
事实上,构造方法在内部变成了
<init>
方法,构造方法方法体内的语句、成员变量的声明、赋值语句事实上都被放到了这个<init>
方法中。
疑问2: 构造方法执行前,Java 就已经给成员变量赋初始值了,那么为什么不能在构造方法调用时(将成员变量作为参数)使用成员变量呢?
经过实验,实际上,的确是在构造方法调用前就给成员变量赋了初始值,
可以故意赋初始值时报除零错误,然后看报错指出的方法和位置,会发现是一个
<init>
方法,而这种带名称尖括号的方法,程序员自己是定义不了的,是 java 自己生成的方法,在构造方法中也可以尝试赋值时故意除零错误,发现报错也是发生在<init>
方法中。
即,在构造方法外的成员变量初始化赋值,和在构造方法方法体内对成员变量赋值,都是在<init>
方法中进行的。之所以不能将成员变量作为构造方法的参数进行对构造方法的调用。因为语意上说不过去,你调用构造方法时,对象还没初始化完成,不应该使用成员变量。你可以理解成 java 就是这么规定的,可能是程序编译运行时,构造方法方法体内和体外的成员变量初始化赋值的语句都是放在
<init>
方法中的,但在赋值前,<init>
实际上需要调用一些函数去创建一个对象实例,而此时会用到构造方法传入的参数,如果这些参数是成员变量,就说不过去了,因为实例压根还没创建出来,自然不会有成员变量。“调用构造方法前会先对成员变量赋值”可以这么理解:你要建造一个钢铁侠的实例,你可以先设定一些属性值,比如说头盔的颜色是红色。然后创建实例时,工厂会按照这个订单上的说明,去创建一个钢铁侠,这个钢铁侠的头盔是红色的。但你不能说你在这个订单上直接附带一个
this.helmetColor
,因为this
是这个实例,还没创建,你就用this
就是非法的,this
都是非法的,this.helmetColor
更加不存在。
public class Person{
public String id;
public int count = 10; // 构造方法执行前,会执行给成员变量赋初始值的操作
public String name = "Jerry";
public Person(){
this("Tom",13);
this.id = "abcde";
}
/* 若写成下面这样,就报错
错误方式1:
public Person(this.name){ // 报错
this("Tom",13);
}
错误方式2:
public Person(){
this(this.name,13); // 在二级重载时使用成员变量作为参数来调用构造方法也是报错
}
但如果是像这样使用成员变量的话,语法不报错,运行结果也和预期一致:
public Person(){
this("Tom",13);
System.out.println(this.name); // Jerry
}
*/
public Person(String name,int age){
this(name,age,40);
System.out.println("玩家默认体重:40");
}
public Person(String name,int age,double weight){
xxxx;
}
}