什么是Java构造方法?Java构造方法怎么定义?Java构造方法怎么调用?Java构造方法有什么作用?Java构造方法可以重载吗?接下来学习一下。
Java构造方法是类中特殊的方法,通过调用构造方法来完成对象的创建,以及对象属性的初始化操作。
Java构造方法怎么定义,请看以下的语法格式:
[修饰符列表] 构造方法名(形式参数列表){
构造方法体;
}
● 构造方法名和类名一致。
● 构造方法用来创建对象,以及完成属性初始化操作。
● 构造方法返回值类型不需要写,写上就报错,包括void也不能写。
● 构造方法的返回值类型实际上是当前类的类型。
● 一个类中可以定义多个构造方法,这些构造方法构成方法重载。
怎么调用构造方法呢,语法格式是:new 构造方法名(实际参数列表);接下来,看以下代码:
图9-12:调用无参数构造方法
以上程序运行结果如下图所示:
图9-13:调用无参数构造方法的运行结果
以上程序的输出结果中虽然第一行看不懂,但起码说明程序是能够正常执行的。我们看到以上Date类当中的代码,并没有发现任何构造方法,为什么可以调用呢?接下来我们来测试一下,把构造方法显示的定义出来:
public class Date {
int year; //年
int month; //月
int day; //日
//构造方法(无参数构造方法)
public Date(){
System.out.println("Date类无参数构造方法执行");
}
}
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
new Date();
System.out.println("main over");
}
}
运行结果如下图所示:
图9-14:测试无参数构造方法
通过以上程序执行结果确实看到了“new Date()”确实调用了Date类当中的无参数构造方法。再看以下程序:
public class Date {
int year; //年
int month; //月
int day; //日
//构造方法(有参数构造方法)
public Date(int year){
System.out.println("带有参数year的构造方法");
}
}
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
new Date();
System.out.println("main over");
}
}
编译报错了,错误信息如下图所示:
图9-15:编译器错误信息提示
通过以上的测试,得出这样一个结论(这是java中语法的规定,记住就行):当一个类没有显示的定义任何构造方法的时候,系统默认提供无参数构造方法,当显示的定义构造方法之后,系统则不再提供无参数构造方法。无参数构造方法又叫做缺省构造器,或者默认构造方法。一般在开发中为了方便编程,建议程序员手动的将无参数构造方法写上,因为不写无参数构造方法的时候,这个默认的构造方法很有可能就不存在了,另外也是因为无参数构造方法使用的频率较高。例如以下代码:
public class Date {
int year; //年
int month; //月
int day; //日
//构造方法(无参数构造方法)
public Date(){
System.out.println("Date类无参数构造方法执行");
}
//构造方法(有参数构造方法)
public Date(int year1){
System.out.println("带有参数year的构造方法");
}
//构造方法(有参数构造方法)
public Date(int year1 , int month1){
System.out.println("带有参数year,month的构造方法");
}
//构造方法(有参数构造方法)
public Date(int year1 , int month1 , int day1){
System.out.println("带有参数year,month,day的构造方法");
}
}
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
new Date();
new Date(2008);
new Date(2008 , 8);
new Date(2008 , 8 , 8);
System.out.println("main over");
}
}
运行结果如下图所示:
图9-16:调用所有构造方法
通过以上的测试可以看出一个类当中可以定义多个构造方法,构造方法是支持重载机制的,具体调用哪个构造方法,那要看调用的时候传递的实际参数列表符合哪个构造方法了。构造方法虽然在返回值类型方面不写任何类型,但它执行结束之后实际上会返回该对象在堆内存当中的内存地址,这个时候可以定义变量接收对象的内存地址,这个变量就是之前所学的“引用”,请看以下代码:
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
Date time1 = new Date();
System.out.println(time1);
Date time2 = new Date(2008);
System.out.println(time2);
Date time3 = new Date(2008 , 8);
System.out.println(time3);
Date time4 = new Date(2008 , 8 , 8);
System.out.println(time4);
System.out.println("main over");
}
}
运行结果如下图所示:
图9-17:构造方法的返回值
以上程序中time1,time2,time3,time4都是引用,输出这些引用的结果是“Date@xxxxx”,对于这个结果目前可以把它等同看做是对象的内存地址(严格来说不是真实的对象内存地址)。通过这个引用就可以访问对象的内存了,例如以下代码:
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
Date time1 = new Date();
System.out.println(time1.year + "年" + time1.month + "月" + time1.day + "日");
Date time2 = new Date(2008);
System.out.println(time2.year + "年" + time2.month + "月" + time2.day + "日");
Date time3 = new Date(2008 , 8);
System.out.println(time3.year + "年" + time3.month + "月" + time3.day + "日");
Date time4 = new Date(2008 , 8 , 8);
System.out.println(time4.year + "年" + time4.month + "月" + time4.day + "日");
System.out.println("main over");
}
}
运行结果如下图所示:
图9-18:通过“引用”访问属性
为什么无论通过哪个构造方法创建Date对象,最终的结果都是“0年0月0日”呢?这是因为所有的构造方法在执行过程中没有给对象的属性手动赋值,系统则自动赋默认值,实际上大部分情况下我们需要在构造方法中手动的给属性赋值,这本来就是构造方法的主要的职责,要不然重载多次构造方法就没有意义了,以上的代码应该这样写,请看:
public class Date {
int year; //年
int month; //月
int day; //日
public Date(){
}
public Date(int year1){
year = year1;
}
public Date(int year1 , int month1){
year = year1;
month = month1;
}
public Date(int year1 , int month1 , int day1){
year = year1;
month = month1;
day = day1;
}
}
public class DateTest {
public static void main(String[] args) {
System.out.println("main begin");
Date time1 = new Date();
System.out.println(time1.year + "年" + time1.month + "月" + time1.day + "日");
Date time2 = new Date(2008);
System.out.println(time2.year + "年" + time2.month + "月" + time2.day + "日");
Date time3 = new Date(2008 , 8);
System.out.println(time3.year + "年" + time3.month + "月" + time3.day + "日");
Date time4 = new Date(2008 , 8 , 8);
System.out.println(time4.year + "年" + time4.month + "月" + time4.day + "日");
System.out.println("main over");
}
}
运行结果如下图所示:
图9-19:通过构造方法给属性赋值
为什么第一个日期输出的是“0年0月0日”?这是因为调用的是无参数构造方法创建的第一个日期对象,在无参数构造方法中没有给属性赋值,则系统赋默认值,所以年月日都是0。那为什么第二个日期输出的是“2008年0月0日”呢?这是因为调用的是“public Date(int year1){ year = year1; }”构造方法创建的第二个日期对象,在这个构造方法当中只是显示的给Date对象的year属性赋值,month和day仍然是系统赋默认值,所以month和day都是0。第三个日期对象是“2008年8月8日”,这是因为在这个对应的构造方法中显示的为year,month,day三个属性都赋值了。在编写以上构造方法的时候需要注意变量名的问题,请看下图:
图9-20:java遵循就近原则
通过以上内容的学习得知,构造方法的作用是专门用来创建对象同时给属性赋值的,它的语法很简单,比普通方法还要简单,因为构造方法名和类名一致,还不需要写返回值类型,使用new就可以调用了。在一个类当中可以同时定义多个构造方法,它们之间构成重载关系。这样就做到了在java中你想要什么就new什么,每一次new都会在堆内存中创建对象,并且对象内部的实例变量被初始化了。
一定要注意,实例变量没有手动赋值的时候系统会默认赋值,但不管是手动赋值还是系统赋默认值,都是在构造方法执行的时候才会进行赋值操作,类加载的时候并不会初始化实例变量的空间,那是因为实例变量是对象级别的变量,没有对象,哪来实例变量,这也是为什么实例变量不能采用“类名”去访问的原因。
public class DateTest {
public static void main(String[] args) {
System.out.println(Date.year);
}
}
编译报错了:
图9-21:实例变量不能直接采用“类名”访问