构造方法的探究

      每当由类构造对象时都要调用该类的构造方法,在Java中,每个类至少有一个构造方法。构造方法可以确保用户正确地构造对象,对对象做初始化工作。构造方法形式如下:[构造方法修饰符] 方法名([形式参数列表])[throws 异常列表] {方法体}构造方法是Java的一个特殊的方法。定义类时通常要定义一个构造方法以辅助创建类的实例。具体地说,构造方法常用于初始化与每个对象有关的变量。在Java中构造方法是与类名称相同的公开的方法成员。在编写类时,不一定每个类都要定义构造方法,在不需要明显给实例
变量赋值初始化时,可以不显式的编写构造方法,因为每个类,编译系统都已经给出了一个不带参数且没有语句内容的默认构造方法,如果用户没有显式定义构造方法,则使用系统给的默认构造方法。系统默认的构造方法除了创建一个空对象外不会完成任何操作。因此,如果需要进行一些预置的初始化工作时,就需要为一个类编写一个或重载多个构造方法。如果用户编写了一个构造方法或者重载了多个构造方法(这是构造方法的多态),则系统给的默认构造方法就无效。例如:public class A {private int x, y;}上例中,用new A ()实例化对象是可以的虽然没有显式写出public A ()构造方法,但是可以用系统定义的默认构造方法。

public class A {

private int x, y;

public A (int a){
x = a;
}
public A (int a, int b){
x = a;
y = b;
}
}
上例中,不能用new A ()实例化对象,因为,用户已经显式的重载了两个带参数的构造方法public A(inta)和public A (int a, int b),系统定义的默认构造方法就不再起作用。只能用new A(int a)或public A(int a, int b)实例化对象。

1. 构造方法的主要特点
1)构造方法的方法名与类名相同。
2)构造方法没有返回值(注意:没有返回
值和返回值为void是不一样的)。
3)构造方法通常被声名为公有的(访问权
限是:public)。
4)构造方法可以带有参数。
5) 构造方法的主要工作是完成对象的部
分或全部成员变量的初始化。
6)构造方法不能在程序中显式地调用,只
能通过new操作符隐式地调用。

构造方法用于初始化新实例化的对象,构
造方法根据所传递的参数设置实例变量的值。
2. 构造方法和普通成员方法的区别
构造方法不同于普通方法之处有几点:
第一,构造方法名必须与类名相同,普通成员方法的方法名一般不能和类名相同。
第二,构造方法不能返回值,因此其方法声名头中没有返回类型。编写类的构造方法时常犯的一个错误是在构造方法的声名中指定void返回类型,编译时具有返回类型的构造方法(即使返回类型为void)将被转换为普通方法(方法名恰恰与类名相同),从而不能作为构造方法调用,这样就导致出现有时很难解释的错误信息。
第三,构造方法不能有以下非访问性质的修饰:abstract,final,native,static,或者synchronized。
3. 一个类的不同构造方法之间的调用一个类可以重载多个构造方法,在多个构造方法之间是可以产生调用关系的。只不过在一个构造方法中只能调用一次一个其它的本类构造方法,而且必须将这个调用语句放在该构造方法的第一句。
例如:
public class A {
A (){
System .out .println ("This
constructor of A has not param eter.") ;
}
A (int i){
this(); // 这是调用的关键点。
System .out.println ("This constructor of A
has param eter, it is" + i);
}
public static void m ain (String[] args){
int n = 8 ;
A stance = new A (n) ;
}
}
从上例中可以看出在类A 的带参构造方法中在第一行使用了this()语句,其意义即指调用前面定义的类A 的无参构造方法。

4. 子类与其父类构造方法的调用继承是面向对象编程语言的一个重要特征。在具有继承关系的类当中,彼此间构造方法的调用相对要复杂一些。
4.1 子类构造方法的特点Java中的子类创建对象时,会自动调用其父类不带参数的构造方法。也就是说,使用子类的任何一种形式的构造方法(无论带参数与否)来创建一个实例对象时,都会自动调用其父类不带参数的构造方法。如果这个类是层层继承下来的,则这个调用会回溯至级别最高的父类,然后依次调用这棵继承树的各个类的无参构造方法。
例如:
class A {
A (){
System .out .println ("This is the
constructor of class A .") ;
}
A (int n){
System .out .println (" This is the
constructor of class A , its param eter is " + n)
;
}
}
class B extends A {
B(){
System .out .println (" This is the
constructor of class B.") ;
}
B(int n){
System .out .println (" This is the
constructor of class B, its param eter is " + n)
;
}
}
public class C extends B{
C(){
System .out .println (" This is the
constructor of class C.") ;
}
C(int n){
System .out .println (" This is the
constructor of class C, its param eter is " + n
+ ".") ;
}
public static void m ain (String[] args){
int m = 20 ;
C child1 = new C() ;
C child2 = new C(m ) ;
}
}
在这里应注意一个问题。当使用子类构造方法时一定要保证其各级父类无参构造方法的存在与正确性。显然在上例中,如果没有定义类A 与类B的无参构造方法是无法通过编译的。针对这个问题,有三种方案解决:第一是保证提供各级父类的无参构造方法;第二是不提供任何构造方法,则各级父类的默认构造方法将起作用;第三是各级父类没有提供无参构造方法,但提供了有参构造方法,则在子类构造方法中以super(参数)来调用各级父类的有参构造方法,从而避免了自动调用无参构造方法的默认方式。
4.2 多态性
子类在继承父类一切的同时,还可以重写父类的方法、拥有自己的数据成员。也就是说,子类是对父类的扩展,因此而成就了面向对象程序设计的多态性。多态性是面向对象编程的另一个重要特征。创建一个子类的实例对象当作父类。形式是:父类名 对象名=子类构造方法以这种形式创建的对象在编译时被当作父类,而在运行时却指向子类。
5. 内部类与外部类的构造方法之间的调用
5.1 非静态内部类
在一个类的内部定义另一个类,这个新定义的类称之为内部类,原来的类就称之为外部类。当外部类含有的是非静态内部类时,对于该外部类的非静态方法,可以通过直接调用内部类的构造方法而创建内部类的对象,从而达到访问内部类的目的。但对于外部类的静态方法,要想访问它的内部类,则必须先调用自身的构造方法创建一个实例对象之后,以“外部类名.内部类名 内
部类对象名 = 外部类对象名. 内部类构造方法”格式来创建内部类的实例对象,从而达到访问内部类的目的。

5.2 静态内部类当一个内部类被定义为static (即静态的)时,则该内部类自动升级为一个正常的类。此当它与包含它的类发生调用关系时,就像普通的类与类之间的调用一样,需要创建彼此的实例对象。但对于外部类的静态方法而言,仍然要遵从前述的步骤与格式创建内部类的对象或者使用“外部类名.内部类名.内部类方法名”格式达到使用内部类方法的目的。

5.3 当内部类是父类时当内部类是另一个类的父类时,问题就会变得比较复杂。因为如前述,要创建类的对象,会首先调用它的父类的构造方法,但这个父类此时是内部类,是无法自动调用的,必须要通过该内部类的外部类的实例对象来访问。于是应在子类中使用“外部类构造方法.super ()”格式来直接访问作为父类的内部类的构造方法,或者创建子类以其父类 (即内部类) 的外部类
为参数的构造方法。
 

猜你喜欢

转载自blog.csdn.net/m0_37708405/article/details/81160342