构造方法(构造器、构造函数)
用于给对象进行初始化,是给与之对应的对象进行初始化,它具有针对性,函数中的一种。在多数情况下,初始化一个对象的最终步骤是去调用这个对象的构造方法。
什么时候使用构造方法呢?分析事物时,发现具体事物一出现,就具备了一些特征,那就将这些特征定义到构造方法内。
构造方法的作用:创建对象;给对象进行初始化。
构造方法和一般方法有什么区别呢?
1)两个方法定义格式不同。
2)构造方法是在对象创建时,就被调用,用于初始化,而且初始化动作只执行一次。
一般方法,是对象创建后,需要调用才执行,可以被调用多次。
构造方法的声明:
1)构造方法的名称必须与所在类的类名一致;
2)构造方法的声明处不能有任何返回值类型的声明;
3)不能在构造方法中使用return返回一个值;
4)不能被static、final、synchronized、abstract、native修饰
构造方法不能被子类继承,所以用final和abstract修饰没有意义。构造方法用于初始化一个新建的对象,所以用static修饰没有意义。多个线程不会同时创建内存地址相同的同一个对象,因此用synchronized修饰没有必要。此外,Java语言不支持native类型的构造方法。
public class Test{
private int x;
public Test() { // 不带参数的构造方法
this(1);
}
public Test(int x) { //带参数的构造方法
this.x=x;
}
// 实例方法和构造方法同名,不是好的编程习惯,容易引起混淆
public int Test(int x) { //不是构造方法
return x++;
}
public void Test(){ //也不是构造方法
x = 5;
}
}
默认构造方法
默认构造方法是没有参数的构造方法,可分为两种:(1)隐含的默认构造方法(2)程序显式定义的默认构造方法。
在Java语言中,每个类至少有一个构造方法。为了保证这一点,如果用户定义的类中没有提供任何构造方法,那么Java语言将自动提供一个隐含的默认构造方法。该构造方法没有参数,用public 修饰,而且方法体为空,格式如下:
public ClassName(){ // 隐含的默认构造方法
}
在程序中也可以显式的定义默认构造方法,它可以是任意的访问级别。例如:
protected Test() { //程序显式定义的默认构造方法
this(5);
}
如果类中显式定义了一个或多个构造方法,并且所有的构造方法都带参数,那么这个类就失去了默认构造方法。
// Test1类有一个隐含的默认构造方法
public class Test1{
}
// Test2类没有默认构造方法
public class Test2{
public Test2(int a){
System.out.println("My Constructor");
}
}
// Test3类有一个显式定义的默认构造方法
public class Test3{
public Test3(){
System.out.println("My Default Constructor");
}
}
构造方法的调用
构造方法只能通过以下方式被调用:
1)当前类的其他构造方法通过this语句调用它。
2)当前类的子类的构造方法通过super语句调用它。
3)在程序中通过new语句调用它。
构造方法的访问级别
构造方法可处于public、protected、默认和private这四种访问级别之一。这里着重介绍构造方法处于private级别的意义。
当构造方法为private级别,意味着只能在当前类中访问它。在当前类的其他构造方法中可以通过this语句调用它,此外还可以在当前类的成员方法中通过new语句调用它。
在以下场合,可以把类的所有构造方法都声明为private类型。
1)在这个类中仅仅包含了一些供其他程序调用的静态方法,没有任何实例方法。其他程序无需创建该类的实例,就能访问类的静态方法。例如 java.lang.Math类就符合这种情况,在Math类中提供了一系列用于数学运算的公共静态方法,为了禁止外部程序创建Math类的实例, Math类的惟一的构造方法是private类型的:
private Math(){}
abstract类型的类也不允许实例化。也许你会问,把Math类定义为如下abstract类型,不是也能禁止Math类被实例化吗?
如果一个类是抽象类,意味着它是专门用于被继承的类,可以拥有子类,而且可以创建具体子类的实例。而JDK并不希望用户创建Math类的子类,在这种情况下,把类的构造方法定义为private类型更合适。
public abstract class Math{…}
2)禁止这个类被继承。当一个类的所有构造方法都是private类型,假如定义了它的子类,那么子类的构造方法无法调用父类的任何构造方法,因此会导致编译错误。把一个类声明为final类型,也能禁止这个类被继承。这两者的区别是:
如果一个类允许其他程序用new语句构造它的实例,但不允许拥有子类,那就把类声明为final类型。
如果一个类既不允许其他程序用new语句构造它的实例,又不允许拥有子类,那就把类的所有构造方法声明为private类型。
由于大多数类都允许其他程序用new语句构造它的实例,因此用final修饰符来禁止类被继承的做法更常见。
3)这个类需要把构造自身实例的细节封装起来,不允许其他程序通过new语句创建这个类的实例,这个类向其他程序提供了获得自身实例的静态方法,这种方法称为静态工厂方法。
构造方法的重载
一个类中,可以有多个构造方法,因为它们的方法名称都相同,所以只能通过参数列表来区分。所以,一个类中如果出现多个构造函数,它们的存在是以重载体现的。
当通过new语句创建一个对象时,在不同的条件下,对象可能会有不同的初始化行为。
构造方法不能被继承,因此不能重写Override,但可以被重载Overload。
Java 中,什么是构造方法?什么是构造方法重载?什么是复制构造方法?
1)方法中的一种,具有针对性,用于给对象进行初始化。当新对象被创建的时候,构造方法会被调用。每一个类都有构造方法。在程序员没有给类提供构造方法的情况下, Java 编译器会为这个类创建一个默认的构造方法。
2)Java 中构造方法重载和方法重载很相似。可以为一个类创建多个构造方法。每一个构造方法必须有它自己唯一的参数列表。
3)Java 不支持像 C++中那样的复制构造方法,这个不同点是因为如果你不自己写构造方法的情况下, Java 不会创建默认的复制构造方法。
注意:
1)所有对象创建时,都需要初始化才可以使用。
2)一个类在定义时,如果没有定义过构造方法,那么该类中会自动生成一个空参数的构造方法,为了方便该类创建对象,完成初始化。如果在类中自定义了构造方法,那么默认的构造方法就没有了。
3)Java语言中,每个类都至少有一个构造器。
4)默认构造器的修饰符与所属类的修饰符一致。
5)一旦显式定义了构造器,则系统不再提供默认构造器。
6)父类的构造器不可被子类继承。
7)一个类可以创建多个重载的构造器。