Java中如何从一个构造函数调用另一个构造函数
技术背景
在Java编程中,一个类可能会有多个构造函数,以满足不同的对象初始化需求。为了避免代码重复,提高代码的可维护性,我们常常需要从一个构造函数调用另一个构造函数。这种调用方式有助于实现构造函数之间的复用,减少冗余代码。
实现步骤
调用同一个类的构造函数
在同一个类中,可以使用this()
或this(args)
来调用另一个构造函数,但这个调用必须是构造函数体中的第一条语句。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11
| public class Foo { private int x;
public Foo() { this(1); }
public Foo(int x) { this.x = x; } }
|
在上述代码中,无参构造函数Foo()
调用了带参构造函数Foo(int x)
。
调用父类的构造函数
使用super()
或super(args)
来调用父类的构造函数,同样,这个调用必须是构造函数体中的第一条语句。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12
| public class SuperClass { public SuperClass() { System.out.println("Inside super class constructor"); } }
public class SubClass extends SuperClass { public SubClass() { System.out.println("Inside sub class constructor"); } }
|
核心代码
同一个类中构造函数的链式调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Rectangle { private int x, y; private int width, height;
public Rectangle() { this(1, 1); }
public Rectangle(int width, int height) { this(0, 0, width, height); }
public Rectangle(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } }
|
调用父类构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Animal { String i;
public Animal() { i = "10"; System.out.println("Animal Constructor :" + i); }
public Animal(String h) { i = "20"; System.out.println("Animal Constructor Habit :" + i); } }
class Cat extends Animal { public Cat() { System.out.println("Cat Constructor"); }
public Cat(String i) { super(i); System.out.println("Cat Constructor with habit"); } }
|
最佳实践
从简单构造函数调用复杂构造函数
尽量从简单的构造函数调用更复杂的构造函数,这样可以确保初始化逻辑的一致性。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class MyClass { int field;
MyClass(int value) { if (value < 0) field = 0; else field = value; }
MyClass() { this(0); } }
|
使用静态方法构造参数
当this()
必须在第一行的限制带来不便时,可以通过静态方法来构造其他构造函数的参数。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class MyClass { public MyClass(double argument1, double argument2) { this(argument1, argument2, getDefaultArg3(argument1, argument2)); }
public MyClass(double argument1, double argument2, double argument3) { this.argument1 = argument1; this.argument2 = argument2; this.argument3 = argument3; }
private static double getDefaultArg3(double argument1, double argument2) { double argument3 = 0; return argument3; } }
|
常见问题
调用必须是第一行
在构造函数中使用this()
或super()
调用其他构造函数时,这个调用必须是构造函数体中的第一条语句,否则会导致编译错误。
示例:
1 2 3 4 5
| public Product(int id, String name, double price) { System.out.println("Calling constructor with price"); this(id, name, price, "DEFAULT"); }
|
避免在显式构造函数调用中引用实例成员
在显式构造函数调用语句中,不能引用任何实例变量、实例方法、内部类、this
或super
。这是Java语言规范(JLS §8.8.7.1)的规定。
构造函数过多时考虑设计模式
如果一个类需要多个构造函数,可能会导致代码复杂,此时可以考虑使用其他设计模式,如Builder模式。
文章参考:
Constructor Chaining in Java
Design Patterns 2: The Builder Pattern and the Telescoping Constructor Anti-Pattern