在同一个类中,是否可能从一个构造函数中调用另一个构造函数?如果可以,怎么做?还有,如何最好地调用另一个构造函数(如果有多种方法)?
在同一个类中,是否可能从一个构造函数中调用另一个构造函数?如果可以,怎么做?还有,如何最好地调用另一个构造函数(如果有多种方法)?
是的,这是可能的:
public class Foo {
private int x;
public Foo() {
this(1);
}
public Foo(int x) {
this.x = x;
}
}
使用super
而不是this
来链接到特定超类构造函数,注意您只能链接到一个构造函数,它必须是构造函数主体中的第一条语句。
另请参见此相关问题,该问题涉及C#,但适用相同原则。
使用 this(args)
。首选模式是从最小的构造函数开始逐步构建。
public class Cons {
public Cons() {
// A no arguments constructor that sends default values to the largest
this(madeUpArg1Value,madeUpArg2Value,madeUpArg3Value);
}
public Cons(int arg1, int arg2) {
// An example of a partial constructor that uses the passed in arguments
// and sends a hidden default value to the largest
this(arg1,arg2, madeUpArg3Value);
}
// Largest constructor that does the work
public Cons(int arg1, int arg2, int arg3) {
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
}
}
您还可以使用更近期提倡的valueOf或只是"of"方法:
public class Cons {
public static Cons newCons(int arg1,...) {
// This function is commonly called valueOf, like Integer.valueOf(..)
// More recently called "of", like EnumSet.of(..)
Cons c = new Cons(...);
c.setArg1(....);
return c;
}
}
要调用父类,请使用super(someValue)
。在构造函数中,调用super必须是第一个调用,否则会出现编译错误。
newCons
实现上一个方法的问题在于,使用setArg1(...)
来更改对象的状态,而该对象的字段最好设置为final。由于我们尽可能地使对象不可变,如果不是完全不可变的话,建造者模式将更正确地解决这个问题。 - YoYoK(A a, B b) { this.a = a; this.b = b; }
。接着,如果b有一个合理的默认值,可以有一个单参数构造函数 K(A a) { this(a, DEFAULT_B); }
,如果也有一个默认的a,则会有一个默认构造函数:K() { this(DEFAULT_A); }
。这是Java中相当常见的惯例。 - Joshua Taylor[注意:我想补充一个方面,其他答案中没有看到的内容:如何克服必须将this()放在第一行的要求限制。]
在Java中,可以通过this()
从构造函数调用同一类的另一个构造函数。但请注意,this
必须放在第一行。
public class MyClass {
public MyClass(double argument1, double argument2) {
this(argument1, argument2, 0.0);
}
public MyClass(double argument1, double argument2, double argument3) {
this.argument1 = argument1;
this.argument2 = argument2;
this.argument3 = argument3;
}
}
this
必须出现在第一行似乎是一个很大的限制,但你可以通过静态方法构造其他构造函数的参数。例如:
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;
// Calculate argument3 here if you like.
return argument3;
}
}
this(...)
), 那么可以合理地假设某处出现了可怕的错误,而设计可能需要重新考虑一下。 - Software Engineerfinal
(最终字段只能被初始化一次)。 - Christian Fries当我需要在代码中调用另一个构造函数(不是第一行),我通常会使用像这样的帮助方法:
class MyClass {
int field;
MyClass() {
init(0);
}
MyClass(int value) {
if (value<0) {
init(0);
}
else {
init(value);
}
}
void init(int x) {
field = x;
}
}
但更常见的做法是,我尝试通过在第一行从简单构造函数调用更复杂的构造函数来实现, 尽可能地这样做。对于上面的例子
class MyClass {
int field;
MyClass(int value) {
if (value<0)
field = 0;
else
field = value;
}
MyClass() {
this(0);
}
}
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;
}
}
这个类包含一组构造函数。每个构造函数都会初始化矩形的某些或所有成员变量。
Rectangle()
中调用第二个构造函数Rectangle(int width, int height)
,而是调用了Rectangle(int x, int y, int width, int height)
? - ANjaNA使用此关键字,我们可以在同一类中的一个构造函数中调用另一个构造函数。
例:
public class Example {
private String name;
public Example() {
this("Mahesh");
}
public Example(String name) {
this.name = name;
}
}
正如其他人已经说过的那样,您使用this(…)
,这被称为显式构造函数调用。
然而,请注意,在此类显式构造函数调用语句中,您不能引用:
this
或super
。如JLS(§8.8.7.1)所述。
是的,在一个类中可以有任意数量的构造函数,并且它们可以被另一个构造函数使用this()
来调用。[请不要将this()
构造函数调用与this
关键字混淆]。this()
或 this(args)
应该是构造函数中的第一行。
例如:
Class Test {
Test() {
this(10); // calls the constructor with integer args, Test(int a)
}
Test(int a) {
this(10.5); // call the constructor with double arg, Test(double a)
}
Test(double a) {
System.out.println("I am a double arg constructor");
}
}
这被称为构造函数重载。
请注意,对于构造函数,仅适用于重载概念,而不是继承或覆盖。
是的,可以从一个构造函数调用另一个构造函数。但是有一条规则需要遵循:如果从一个构造函数调用另一个构造函数,则该新构造函数调用必须是当前构造函数中的第一条语句。
public class Product {
private int productId;
private String productName;
private double productPrice;
private String category;
public Product(int id, String name) {
this(id,name,1.0);
}
public Product(int id, String name, double price) {
this(id,name,price,"DEFAULT");
}
public Product(int id,String name,double price, String category){
this.productId=id;
this.productName=name;
this.productPrice=price;
this.category=category;
}
}
因此,类似以下内容将无法正常工作。
public Product(int id, String name, double price) {
System.out.println("Calling constructor with price");
this(id,name,price,"DEFAULT");
}
此外,在继承的情况下,当子类对象被创建时,首先调用超类构造函数。
public class SuperClass {
public SuperClass() {
System.out.println("Inside super class constructor");
}
}
public class SubClass extends SuperClass {
public SubClass () {
//Even if we do not add, Java adds the call to super class's constructor like
// super();
System.out.println("Inside sub class constructor");
}
}
因此,在这种情况下,还有另一个构造函数调用在任何其他语句之前被声明。
我会告诉你一个简单的方法
有两种类型的构造函数:
我将通过一个示例来解释。
class ConstructorDemo
{
ConstructorDemo()//Default Constructor
{
System.out.println("D.constructor ");
}
ConstructorDemo(int k)//Parameterized constructor
{
this();//-------------(1)
System.out.println("P.Constructor ="+k);
}
public static void main(String[] args)
{
//this(); error because "must be first statement in constructor
new ConstructorDemo();//-------(2)
ConstructorDemo g=new ConstructorDemo(3);---(3)
}
}
注意:this必须是构造函数中的第一条语句。
public Foo() { } public Foo(int x) { this.x = x; } public Foo(int x, int y) { this.x = x; this.y = y }
- Augusto