一、对象的构造及初始化
1.1 如何初始化对象
public static void main(String[] args) { int a; System.out.println(a); }
上述代码在方法内部使用了一个定义但未初始化的局部变量,编译会报错,在使用前要对其进行赋值。
public static void main(String[] args) { Date date=new Date(); date.printDay(); System.out.println("====="); date.Setday(2023,3,22); date.printDay(); }
上述代码实例化一个对象并利用函数Setday对其赋值,但在赋值前并未报错,这是因为在成员变量未赋初值时,编译器会给类中的成员变量依其类型给一个默认值。每次创建对象后都要调用Setday为对象赋值,那对象该如何初始化呢?
1.2 构造方法
1. 概念
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
public class Date { public int year; public int month; public int day; public void printDay(){ System.out.println(this.year+"/"+this.month+"/"+this.day); } public Date(int year,int month,int day){ this.year=year; this.month=month; this.day=day; } public static void main(String[] args) { Date date=new Date(2023,3,22); date.printDay(); } }
注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。
2. 特性
1. 名字必须与类名相同。
2. 没有返回值类型,设置为void也不行。
3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)。
4. 构造方法可以重载
public class Date { public int year; public int month; public int day; public void printDay(){ System.out.println(this.year+"/"+this.month+"/"+this.day); } //方法重载 //无参的构造方法(用于对象属性值都相同) public Date(){ this.year=2023; this.month=3; this.day=22; } //有参的构造方法(用于对象属性值不相同) public Date(int year,int month,int day){ this.year=year; this.month=month; this.day=day; } public static void main(String[] args) { Date date=new Date();///传不传参都可以 date.printDay(); } }
5.如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。
注意:一旦用户定义构造方法,编译器则不再生成。
public class Date { public int year; public int month; public int day; public void printDay(){ System.out.println(this.year+"/"+this.month+"/"+this.day); } public static void main(String[] args) { Date date=new Date() ; date.printDay(); } }
上述Date类中,没有定义任何构造方法,编译器会默认生成一个不带参数的构造方法。
6. 构造方法中,可以通过this调用其他构造方法来简化代码。
public class Date { public int year; public int month; public int day; public void printDay(){ System.out.println(this.year+"/"+this.month+"/"+this.day); } public Date(int year,int month,int day){ this.year=year; this.month=month; this.day=day; } public Date(){ this(2023,3,22); } public static void main(String[] args) { Date date=new Date(); date.printDay(); }
注意:this(...)必须是构造方法中的第一条语句,不能形成环。
public Date(){ //环 this(2023,3,22); } public Date(int year, int month, int day) { this(); }
7. 绝大多数情况下使用public来修饰,特殊场景下会被private修饰。
1.3 默认初始化
上述中局部变量使用时必须初始化,而成员变量则不用,这是为什么呢?
public 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; } public static void main(String[] args) { Date date=new Date(); date.printDay(); } }
要弄清楚这个问题,要了解new关键字的作用
Date date=new Date();
程序中只是一条语句,而在JVM层面,则做了很多事:检测对象对应的类是否加载了,如果没有加载则加载;为对象分配内存空间;处理并发安全问题;初始化所分配的空间;设置对象头信息;调用构造方法,给对象中各个成员赋值。
数据类型 | 默认值 |
byte | 0 |
char | ‘\u0000’ |
short | 0 |
int | 0 |
long | 0L |
boolean | false |
float | 0.0f |
double | 0.0 |
reference | null |
1.4 就地初始化
在声明成员变量时就赋初值
public class Date { public int year = 2023; public int month = 3; public int day = 22; public Date(){ } public Date(int year, int month, int day) { } public static void main(String[] args) { Date d1 = new Date(2022,3,22); Date d2 = new Date(); } }
注意:代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中。