如何初始化对象
在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。
要让上述代码通过编译,非常简单,只需在正式使用a之前,给a设置一个初始值即可。
如果是对象:
需要调用之前写的SetDate方法才可以将具体的日期设置到对象中。
//Data类
class Data {
public int year;
public int month;
public int day;
public void setData(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void printData() {
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
}
public class test {
public static void main(String[] args) {
Data data = new Data();
data.printData();
data.setData(1998, 9, 18);
data.printData();
}
}
通过上述例子发现两个问题:
- 每次对象创建好后调用SetDate方法设置具体日期,比较麻烦,那对象该如何初始化?
- 局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?
构造方法
概念
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且
在整个对象的生命周期内只调用一次。
class Data {
public int year;
public int month;
public int day;
// 构造方法:
// 名字与类名相同,没有返回值类型,设置为void也不行
// 一般情况下使用public修饰
// 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
public Data(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("调用了一次还有三个参数的构造方法");
}
public void printData() {
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
}
public class test {
public static void main(String[] args) {
Data data = new Data(1998, 9, 18);//调用构造方法
data.printData();
}
}
注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。
特性
- 名字必须与类名相同
- 没有返回值类型,设置为void也不行
- 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
- 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
- 如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。
- 用户一旦定义过构造方法 则编译器将不在自动生成
class Date {
public int year;
public int month;
public int day;
//含有三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("调用了一次还有三个参数的构造方法");
}
//不含参数的构造方法
public Date(){
this.year = 1900;
this.month = 1;
this.day = 1;
}
//三个参数的构造方法和不含参数的构造方法之间形成了重载
public void printDate() {
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
}
例如这里的Date类中有一个三个参数的构造方法 此时如果在创建一个对象但是不传参数则会报错 因为编译器不会再给你创建一个无参数的构造方法 此时必须自己才实现一个无参数的构造方法才还可以继续使用
默认初始化
为什么局部变量在定义时要初始化 而成员变量则可以不初始化呢?
要搞清楚这个过程,就需要知道 new 关键字背后所发生的一些事情:
Date d = new Date(2021,6,9);
在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍下:
-
检测对象对应的类是否加载了,如果没有加载则加载
-
为对象分配内存空间
-
处理并发安全问题
比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突 -
初始化所分配的空间
即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:
-
设置对象头信息
-
调用构造方法,给对象中各个成员赋值
就地初始化
class Date {
public int year = 1998;
public int month = 1;
public int day = 1;
//在定义时就初始化
public void printDate() {
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
}