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

时间:2008-11-12 20:10:20

标签: java constructor

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

23 个答案:

答案 0 :(得分:2745)

是的,有可能:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

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

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

另请参阅this related question,这是关于C#但适用相同原则的地方。

答案 1 :(得分:224)

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

答案 2 :(得分:192)

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

在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 :(得分: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;
   }
}

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

class MyClass {
   int field;

   MyClass(int value) {
      if (value<0)
         field = 0;
      else
         field = value;
   }
   MyClass() {
      this(0);
   }
}

答案 4 :(得分: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;
    }

}

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

答案 5 :(得分:15)

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

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

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

如JLS(§8.8.7.1)所述。

答案 6 :(得分: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");
}

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

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

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

答案 7 :(得分: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");
    }
}

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

答案 8 :(得分:9)

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

两种类型的构造函数:

  1. 默认构造函数
  2. 参数化构造函数
  3. 我将在一个例子中解释

    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. 这是Name less Object。这会自动调用默认构造函数。 3.这会调用参数化构造函数。
    4. 注意: 这必须是构造函数中的第一个语句。

答案 9 :(得分:7)

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

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 :(得分: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
}

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

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

希望这有帮助。

答案 11 :(得分:7)

你可以使用&#34;这个&#34;来自同一个类的另一个构造函数的构造函数。关键词。 示例 -

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 as arg constructor ..

答案 12 :(得分: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);
   }

答案 13 :(得分:5)

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

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

Setter methods or constructors

答案 14 :(得分:5)

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

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

class LambdaInitedClass {

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

用...来称呼它

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

答案 15 :(得分:4)

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

    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 :(得分:4)

它被称为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

答案 17 :(得分:4)

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

但是,这样的调用必须是构造函数的 first 语句。要克服此限制,请使用this answer

答案 18 :(得分:1)

最初是由米尔科·克莱姆(Mirko Klemm)的分析者提出的,经过稍微修改后可以解决该问题:

仅出于完整性考虑:还有Instance initialization block总是在调用任何其他构造函数之前执行。它仅由您的类定义主体中某处的语句“ {...}”块组成。您甚至可以拥有多个。您无法调用它们,但是如果您想在构造函数中重用某些代码,则它们类似于“共享构造函数”代码,类似于调用方法。

所以就您而言

{ 
  System.out.println("this is shared constructor code executed before the constructor");
  field1 = 3;
}

还有一个“静态”版本,用于初始化静态成员:“ static {...}”

答案 19 :(得分:1)

我更喜欢这样:

    class User {
        private long id;
        private String username;
        private int imageRes;

    public User() {
        init(defaultID,defaultUsername,defaultRes);
    }
    public User(String username) {
        init(defaultID,username, defaultRes());
    }

    public User(String username, int imageRes) {
        init(defaultID,username, imageRes);
    }

    public User(long id, String username, int imageRes) {
        init(id,username, imageRes);

    }

    private void init(long id, String username, int imageRes) {
        this.id=id;
        this.username = username;
        this.imageRes = imageRes;
    }
}

答案 20 :(得分:0)

是的,您可以从其他构造函数调用构造函数。例如:

$date1 = new DateTime("2019-04-16"); 
$date2 = new DateTime("2019-08-17"); 
$interval = $date1->diff($date2);
return $interval;

您还可以阅读以下内容的详细信息 Constructor Chaining in Java

答案 21 :(得分:0)

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

示例:-

@model MSFSAddons.Models.ViewModels.FileManagerViewModel

@{
   ViewData["Title"] = "Upload";
   Layout = "~/Themes/FrontEnd/_MyProfile.cshtml";
 }

<form enctype="multipart/form-data" asp-controller="FileManager" asp-action="Put" method="post">
<dl>
    <dt>
        <label asp-for="File"></label>
    </dt>
    <dd>
        <input asp-for="File" type="file">
        <span asp-validation-for="File"></span>
    </dd>
</dl>
 <input asp-page-handler="Upload" class="btn" type="submit" value="Upload" />
</form>

答案 22 :(得分:0)

它被称为构造函数链接。构造函数链接是从另一个构造函数中调用一个构造函数的过程,该过程与当前对象有关。构造函数链接可以通过两种方式完成:

1.在同一个类中:可以在同一个类中的构造函数中使用this()关键字来完成 2.从基类:通过使用super()关键字从基类调用构造函数。