如何在 Java 中从另一个调用一个构造函数?

是否可以从另一个(在同一类中,而不是在子类中)调用构造函数?如果是,怎么办?调用另一个构造函数的最佳方法是什么(如果有几种方法可以做到)?

答案

对的,这是可能的:

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 的调用必须是构造函数中的第一个调用,否则会出现编译器错误。

[ 注意:我只想添加一个方面,而我在其他答案中没有看到:如何克服 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;

  }

}

当我需要从代码内部调用另一个构造函数时(不在第一行中),我通常使用如下的辅助方法:

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);
   }
}

在构造函数中,可以使用this关键字调用同一类中的另一个构造函数。这样做称为显式构造函数调用

这是另一个 Rectangle 类,其实现与 Objects 部分中的实现不同。

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;
    }

}

此类包含一组构造函数。每个构造函数都会初始化矩形的一些或所有成员变量。

正如大家已经说过的,您可以使用this(…) ,这称为显式构造函数调用

但是,请记住,在这样的显式构造函数调用语句中, 您可能不会引用

  • 任何实例变量
  • 任何实例方法
  • 此类中声明的任何内部类或任何超类,或
  • this
  • super

如 JLS(第 8.8.7.1 节)所述。

是的,可以从另一个调用一个构造函数。但是有一个规则。如果从一个构造函数调用另一个,则

新的构造函数调用必须是当前构造函数中的第一条语句

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");
    }
}

因此,在这种情况下,在任何其他语句之前也首先声明了另一个构造函数调用。

是的,一个类中可以存在任意数量的构造函数,并且其他构造函数可以使用this()调用它们this()请不要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");
    }
}

这称为构造函数重载。
请注意,对于构造函数,仅重载概念适用,而不继承或重写。

我会告诉你一个简单的方法

两种类型的构造函数:

  1. 默认构造函数
  2. 参数化构造函数

我将在一个例子中解释

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)    
       }
   }

在上面的示例中,我展示了 3 种呼叫类型

  1. 对此的 this()调用必须是构造函数中的第一条语句
  2. 这是没有名称的对象。这会自动调用默认构造函数。 3. 这将调用 Parameterized 构造函数。

注意: 这必须是构造函数中的第一条语句。

您可以使用 “this” 关键字来构造同一类的另一个构造函数。范例 -

class This1
{
    This1()
    {
        this("Hello");
        System.out.println("Default constructor..");
    }
    This1(int a)
    {
        this();
        System.out.println("int as arg constructor.."); 
    }
    This1(String s)
    {
        System.out.println("string as arg constructor..");  
    }

    public static void main(String args[])
    {
        new This1(100);
    }
}

输出 - 字符串作为 arg 构造函数.. 默认构造函数.. int 作为 arg 构造函数..