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

ash*_*lal 2144 java constructor

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

Jon*_*eet 2853

对的,这是可能的:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

    public Foo(int x) {
        this.x = x;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这必须出现在第一行,但您可以在调用之前在构造函数中进行计算:您可以在第一行的this()的参数中使用静态方法,并封装在调用之前必须执行的任何计算到那个静态方法中的另一个构造函数.(我已将此作为单独的答案添加). (39认同)
  • 所以我认为不可能调用超级构造函数和同一个类的另一个构造函数,因为它们都需要成为第一行? (29认同)
  • @ gsingh2011:的确如此.你只能链接到*one*其他构造函数. (28认同)
  • @ gsingh2011我知道它已经晚了但作为一种方法,你可以使用this(...)调用重载的构造函数,然后在那个重载的构造函数中,你可以使用super(...)调用基类的构造函数 (7认同)
  • @JustinTime:同样,它取决于"创建"的含义 - 对象是"创建的",因为它的内存已分配,并且在执行任何构造函数体之前设置类型.构造函数是初始化而不是创建.特别是,对象的类型从一开始就是它的"最终"类型 - 所以如果你从构造函数调用任何虚方法,你将获得最具体的覆盖调用.我相信这与C++不同. (3认同)
  • @Andrej:这确实是“从另一个构造函数调用一个构造函数”,但它不会做OP想要的事情,即通过多个构造函数初始化单个对象,一个链接到另一个构造函数。通过在一个构造函数调用中创建一个单独的对象来创建两个对象根本不是一回事。 (2认同)

Jos*_*osh 238

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用最近提倡的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;
    }
} 
Run Code Online (Sandbox Code Playgroud)

要调用超类,请使用super(someValue).对super的调用必须是构造函数中的第一个调用,否则您将收到编译器错误.

  • 如果使用了许多构造函数参数,请考虑构建器.参见Joshua Bloch的"Effective Java"第2项. (27认同)
  • 使用工厂方法`newCons`实现最后一种方法的问题在于,您正在尝试使用`setArg1(...)`来更改对象的状态,这应该最有可能将其字段设置为final .因为我们试图尽可能地保持对象不可变,如果不是完全的,构建器模式将更准确地解决这个问题. (5认同)
  • @ RodneyP.Barbati在Java中,低友善度的构造函数调用大友善度的构造函数*然后不执行其他任何操作*是很常见的。如果类K具有例如两个最终字段a,b,则“通用构造函数”将为`K(A a,B b){this.a = a; this.b = b; }`。然后,如果`b`具有合理的默认值,则可以有一个单参数构造函数`K(A a){this(a,DEFAULT_B); }`,如果还有默认的`a`,我们有一个默认的构造函数:`K(){this(DEFAULT_A); }`。这是Java中非常普遍的约定。 (3认同)
  • 你不想做 :: public Cons() { this(madeUpArg1Value,madeUpArg2Value); } (2认同)

Chr*_*ies 196

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

在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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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;

  }

}
Run Code Online (Sandbox Code Playgroud)

  • 我同意*非常复杂的转换可能表明设计问题.但是1)有一些简单的转换对于这些转换可能是有用的 - 并非所有构造函数都只是对其他构造函数的线性投影,2)可能存在其他情况,这些信息可能成为手,如支持遗留代码.(虽然我同意你的结论,但我不明白为什么它会证明投票是正当的). (13认同)
  • 确实,您可以通过这种方式调用静态方法,以便对参数值执行复杂的计算,这很好.但是,如果有人认为在构造函数委托之前需要代码(`this(...)`)那么可以合理地假设某个地方出现了一个可怕的错误并且设计可能需要重新思考一下. (11认同)
  • @ RodneyP.Barbati:我按照你描述的方式看到了一些问题:a)这样做是不可能在构造函数中说明静态方法的使用(这是示例的意图); - )和b)如果按照自己的方式进行,则字段不能是"final"(最终字段只能初始化一次). (2认同)

Kaa*_*mel 38

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

class MyClass {
   int field;


   MyClass() {
      init(0);
   } 
   MyClass(int value) {
      if (value<0) {
          init(0);
      } 
      else { 
          init(value);
      }
   }
   void init(int x) {
      field = x;
   }
}
Run Code Online (Sandbox Code Playgroud)

但是大多数情况下,我尝试通过从第一行中较简单的构造函数调用更复杂的构造函数来反过来做到这一点.对于上面的例子

class MyClass {
   int field;

   MyClass(int value) {
      if (value<0)
         field = 0;
      else
         field = value;
   }
   MyClass() {
      this(0);
   }
}
Run Code Online (Sandbox Code Playgroud)


ami*_*ura 26

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

}
Run Code Online (Sandbox Code Playgroud)

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


Ani*_*rgi 21

使用this关键字,我们可以从同一类中的另一个构造函数调用一个构造函数。

例子 :

public class Example {

    private String name;

    public Example() {
        this("Mahesh");
    }

    public Example(String name) {
        this.name = name;
    }

}
Run Code Online (Sandbox Code Playgroud)


olo*_*ovb 15

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

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

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

如JLS(§8.8.7.1)中所述.


S R*_*nya 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,像下面这样的东西是行不通的.

public Product(int id, String name, double price) {
    System.out.println("Calling constructor with price");
    this(id,name,price,"DEFAULT");
}
Run Code Online (Sandbox Code Playgroud)

此外,在继承的情况下,当创建子类的对象时,首先调用超类构造函数.

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,还会在任何其他语句之前声明另一个构造函数调用.


Uts*_*Uts 9

是的,任何数量的构造函数都可以存在于类中,并且可以使用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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Shi*_*ari 9

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

两种类型的构造函数:

  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)    
       }
   }                  
Run Code Online (Sandbox Code Playgroud)

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

  1. this()调用this必须是构造函数中的第一个语句
  2. 这是Name less Object.这会自动调用默认构造函数.3.这会调用参数化构造函数.

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

  • 主方法中有以下内容:**// this(); 错误,因为"必须是构造函数中的第一个语句**这个语句没有多大意义.如果你试图说_this()_不能从_main_方法内部调用,那么是的,它不能是因为main是静态的,不会参考_this()_ (4认同)

ABH*_*ANA 7

您可以使用"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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Aks*_*wad 7

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

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

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


Get*_*erZ 7

很简单

public class SomeClass{

    private int number;
    private String someString;

    public SomeClass(){
        number = 0;
        someString = new String();
    }

    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 )
        this.setString(someString);
    }

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

现在这里有一些额外的小功劳:

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

希望这可以帮助。


Joh*_*ane 7

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

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


小智 6

是的,可以使用一个来自另一个构造函数 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);
   }
Run Code Online (Sandbox Code Playgroud)


S. *_*yol 5

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

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

Setter方法或构造函数


Rod*_*ati 5

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

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

class LambdaInitedClass {

   public LamdaInitedClass(Consumer<LambdaInitedClass> init) {
       init.accept(this);
   }
}
Run Code Online (Sandbox Code Playgroud)

叫它......

 new LambdaInitedClass(l -> { // init l any way you want });
Run Code Online (Sandbox Code Playgroud)


Neg*_*Rox 5

我知道这个问题有很多例子,但我将发现的内容放在这里来分享我的想法。有两种方法可以链接构造函数。在同一个类中,您可以使用此关键字。在继承中,需要使用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");
        }
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

是的,您可以从另一个构造函数调用构造函数。例如:

public class Animal {
    private int animalType;

    public Animal() {
        this(1); //here this(1) internally make call to Animal(1);
    }

    public Animal(int animalType) {
        this.animalType = animalType;
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以阅读Java 中的构造函数链的详细信息