提问



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

最佳参考


对的,这是可能的:


public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

    public Foo(int x) {
        this.x = x;
    }
}


要链接到特定的超类构造函数而不是同一类中的一个,请使用super而不是this。请注意,您只能链接到一个构造函数它必须是构造函数体中的第一个语句


另请参阅此相关问题,该问题与C#相关,但适用相同的原则。

其它参考1


使用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(asdf)。对super的调用必须是构造函数中的第一个调用,否则您将收到编译器错误。

其它参考2


[[注意:我只想添加一个方面,我在其他答案中没有看到:如何克服这个()必须在第一行的要求的限制。)]]


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

  }

}

其它参考3


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


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

其它参考4


在构造函数中,您可以使用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;
    }

}


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

其它参考5


正如大家已经说过的那样,你使用this(…),这被称为显式构造函数调用。


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



  • 任何实例变量或

  • 任何实例方法或

  • 在此类或任何超类中声明的任何内部类,或

  • this

  • super



如JLS(§8.8.7.1)中所述。

其它参考6


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


两个类型的构造函数:



  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. 这是Name less Object。这会自动调用默认构造函数。
    3.这称为参数化构造函数。



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

其它参考7


是的,任何数量的构造函数都可以存在于类中,并且可以由另一个构造函数使用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");
    }
}


这称为构造函数重载。

请注意,对于构造函数,只有重载概念适用,而不是继承或覆盖。

其它参考8


您可以使用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构造函数..

其它参考9


从另一个构造函数调用构造函数


class MyConstructorDemo extends ConstructorDemo
{
    MyConstructorDemo()
    {
        this("calling another constructor");
    }
    MyConstructorDemo(String arg)
    {
        System.out.print("This is passed String by another constructor :"+arg);
    }
}


您也可以使用super()调用来调用父构造函数

其它参考10


是的,可以使用this()从另一个构建函数调用


class Example{
   private int a = 1;
   Example(){
        this(5); //here another constructor called based on constructor argument
        System.out.println("number a is "+a);   
   }
   Example(int b){
        System.out.println("number b is "+b);
   }

其它参考11


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



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



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

其它参考12


关键字 this 可用于从构造函数中调用构造函数,在为类编写多个构造函数时,有时您希望从另一个构建函数中调用一个构造函数避免重复的代码。


Bellow是一个链接,我解释了关于构造函数和getters()和setters()的其他主题,我使用了一个带有两个构造函数的类。我希望解释和例子可以帮到你。


Setter方法或构造函数

其它参考13


有一些设计模式可以满足复杂结构的需要 - 如果不能简洁地完成,可以创建工厂方法或工厂类。


使用最新的java和lambdas的添加,很容易创建一个构造函数,它可以接受你想要的任何初始化代码。


class LambdaInitedClass {

   public LamdaInitedClass(Consumer<LambdaInitedClass> init) {
       init.accept(this);
   }
}


叫它......


 new LambdaInitedClass(l -> { // init l any way you want });

其它参考14


很简单


public class SomeClass{

    int number;
    String someString;

    public SomeClass(){
        number = 0;
    }

    public SomeClass(int number){
        this(); //set the class to 0
        this.setNumber(number); 
    }

    public SomeClass(int number, String someString){
        this(number); //call public SomeClass( int number )
    }

    public void setNumber(int number){
        this.number = number;
    }
    public void setString(String someString){
        this.someString = someString;
    }
    //.... add some accessors
}


现在这里有一些额外的小额信贷:


public SomeOtherClass extends SomeClass {
    public SomeOtherClass(int number, String someString){
         super(number, someString); //calls public SomeClass(int number, String someString)
    }
    //.... Some other code.
}


希望这可以帮助。

其它参考15


我知道这个问题有很多例子,但我发现我在这里分享我的想法。链式构造函数有两种方法。在同一个类中,您可以使用此关键字。在继承中,您需要使用super关键字。


    import java.util.*;
    import java.lang.*;

    class Test
    {  
        public static void main(String args[])
        {
            Dog d = new Dog(); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.
            Dog cs = new Dog("Bite"); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.

            // You need to Explicitly tell the java compiler to use Argument constructor so you need to use "super" key word
            System.out.println("------------------------------");
            Cat c = new Cat();
            Cat caty = new Cat("10");

            System.out.println("------------------------------");
            // Self s = new Self();
            Self ss = new Self("self");
        }
    }

    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 Dog extends Animal
    {
        public Dog()
        {
            System.out.println("Dog Constructor");
        }
        public Dog(String h)
        {
            System.out.println("Dog Constructor with habit");
        }
    }

    class Cat extends Animal
    {
        public Cat()
        {
            System.out.println("Cat Constructor");
        }
        public Cat(String i)
        {
            super(i); // Calling Super Class Paremetrize Constructor.
            System.out.println("Cat Constructor with habit");
        }
    }

    class Self
    {
        public Self()
        {
            System.out.println("Self Constructor");
        }
        public Self(String h)
        {
            this(); // Explicitly calling 0 args constructor. 
            System.out.println("Slef Constructor with value");
        }
    }

其它参考16


它被称为Telescoping Constructor反模式或构造函数链接。是的,你绝对可以。我在上面看到了很多例子,我想补充说,如果你知道你只需要两三个构造函数,那就可以了。但如果您需要更多,请尝试使用不同的设计模式,如Builder模式。例如:


 public Omar(){};
 public Omar(a){};
 public Omar(a,b){};
 public Omar(a,b,c){};
 public Omar(a,b,c,d){};
 ...


你可能需要更多。在这种情况下,Builder模式将是一个很好的解决方案。这是一篇文章,它可能会有所帮助
https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e[44]

其它参考17


您可以通过this(...)关键字调用另一个构造函数(当您需要从同一个类调用构造函数时)或super(...)关键字
(当你需要从超类中调用构造函数时)。[45] [46]


但是,这样的调用必须是构造函数的第一个语句。要克服此限制,请使用此答案。