第一章 面向对象
第二章 异常
第三章 数组
第四章 常用类
第五章 集合
第六章 IO流
第七章 线程
第八章 反射
第九章 Socket编程

java构造方法Constructor

 

什么是构造方法?构造方法怎么定义?构造方法怎么调用?构造方法有什么作用?构造方法可以重载吗?接下来学习一下。

构造方法是类中特殊的方法,通过调用构造方法来完成对象的创建,以及对象属性的初始化操作。

构造方法怎么定义,请看以下的语法格式:

 

[修饰符列表] 构造方法名(形式参数列表){

    构造方法体;

}

 

  • 构造方法名和类名一致。
  • 构造方法用来创建对象,以及完成属性初始化操作。
  • 构造方法返回值类型不需要写,写上就报错,包括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:实例变量不能直接采用“类名”访问 

全部教程