当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在Java中调用另一个构造函数?》经验,为你挑选了15个好方法。

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



1> Jon Skeet..:

对的,这是可能的:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

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

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

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


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

2> Josh..:

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


如果使用了许多构造函数参数,请考虑构建器.参见Joshua Bloch的"Effective Java"第2项.
使用工厂方法`newCons`实现最后一种方法的问题在于,您正在尝试使用`setArg1(...)`来更改对象的状态,这应该最有可能将其字段设置为final .因为我们试图尽可能地保持对象不可变,如果不是完全的,构建器模式将更准确地解决这个问题.
@ 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> Christian Fr..:

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

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

  }

}


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

4> Kaamel..:

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

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



5> amila isura..:

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

}

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



6> olovb..:

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

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

任何实例变量

任何实例方法

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

this 要么

super.

如JLS(§8.8.7.1)中所述.



7> S R Chaitany..:

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

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

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

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



8> Uts..:

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

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



9> Shiva Nandam..:

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

两种类型的构造函数:

    默认构造函数

    参数化构造函数

我将在一个例子中解释

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种类型的呼叫

    this()调用this必须是构造函数中的第一个语句

    这是Name less Object.这会自动调用默认构造函数.3.这会调用参数化构造函数.

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


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

10> ABHISHEK RAN..:

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



11> Akshay Gaikw..:

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

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

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



12> GetBackerZ..:

很简单

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

希望这可以帮助。



13> 小智..:

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



14> S. Mayol..:

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

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

Setter方法或构造函数



15> Rodney P. Ba..:

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

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

class LambdaInitedClass {

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

叫它......

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

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有