问:

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

答1:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

对的,这是可能的:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

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

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

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

所以我认为不可能调用同一个类的超级构造函数和另一个构造函数,因为两者都需要成为第一行?

@gsingh2011:确实。您只能链接到另一个构造函数。

这必须出现在第一行,但您可以在调用之前在构造函数中进行计算:您可以在第一行的 this() 的参数中使用静态方法,并封装必须在调用之前执行的任何计算到该静态方法中的另一个构造函数。 (我已将此作为单独的答案添加)。

@gsingh2011 我知道已经晚了,但是作为一种解决方法,您可以使用 this(...) 调用重载构造函数,然后在该重载构造函数中,您可以使用 super(...) 调用基类的构造函数

@Andrej:这确实是“从另一个调用一个构造函数”,但它不会做OP想要的,即通过多个构造函数初始化一个对象,一个链接到另一个。通过在一个构造函数调用中创建一个单独的对象来创建两个对象根本不是一回事。

答2:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

使用 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。当我们试图尽可能多地保持对象不可变时,如果不是完全不可变的话,构建器模式将更正确地解决这个问题。

你不想这样做 :: public Cons() { this(madeUpArg1Value,madeUpArg2Value); }

@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 中非常常见的约定。

@RodneyP.Barbati 如果您有一个 final 字段(因此必须设置它),那么默认构造函数必须设置它。如果您的更高数量的构造函数调用默认构造函数(必须在其他任何事情之前完成),那么更高数量的构造函数永远没有任何选项来设置任何这些字段。

答3:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

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

  }

}

确实,您可以通过这种方式调用静态方法,以便对参数值执行复杂的计算,这很好。但是,如果有人认为在构造函数委托 (this(...)) 之前需要代码,那么可以合理地假设某处发生了可怕的错误,并且可能需要重新考虑设计。

我同意非常复杂的转换可能表明存在设计问题。但是 1) 有一些简单的转换可能对它们有用 - 并非所有构造函数都只是对其他人的线性投影,并且 2) 可能存在其他情况,这些信息可能会成为手,比如支持遗留代码。 (虽然我同意你的结论,但我不明白为什么它会证明投反对票是合理的)。

@RodneyP.Barbati:我发现按照您描述的方式进行操作时存在一些问题:a)这样做无法说明在构造函数中使用静态方法(这就是示例的意图); -) 和 b) 如果您按照自己的方式进行操作,则字段不能为 final(最终字段只能初始化一次)。

@RodneyP.Barbati:另外两个方面:c)我认为您应该始终在一个点进行对象初始化,这必须是最通用的构造函数。如果对象初始化需要复杂的任务(对象初始化不是懒惰的)或检查或获取一些资源(如文件),那么您喜欢只做一次。并且 d) 添加另一个参数(比如参数 4),其初始化取决于参数 1 到参数 3 的值,您必须更改您的情况下的所有构造函数,而在这里您只需添加一个并让 3-arg 调用 4 -arg 构造函数。

有关克服“必须是构造函数中的第一个语句”限制的更通用方法,请参阅 this answer。它适用于 super() 和 this() 调用。

答4:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

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

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:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

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

}

此类包含一组构造函数。每个构造函数初始化矩形的部分或全部成员变量。

为什么不调用 Rectangle() 中的 Rectangle(int width, int height) 而不是 Rectangle(int x, int y, int width, int height) 的第二个构造函数?

@RodneyP.Barbati 在这种情况下我不能同意。该模式不允许使用 final 字段。

答6:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

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

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

任何实例变量或

任何实例方法或

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

这个或

极好的。

如 JLS (§8.8.7.1) 中所述。

答7:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

是的,一个类中可以存在任意数量的构造函数,并且它们可以由另一个构造函数使用 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:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

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

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

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

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

答9:

huntsbot.com – 高效赚钱,自由工作

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

例子 :-

public class Example {
   
      private String name;
   
      public Example() {
          this("Mahesh");
      }

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

 }

答10:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

我告诉你一个简单的方法

有两种类型的构造函数:

默认构造函数参数化构造函数

我将在一个例子中解释

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 的调用必须是构造函数中的第一条语句 This is Nameless Object。这会自动调用默认构造函数。 3.这会调用参数化构造函数。

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

您在 main 方法中有以下内容: //this();错误,因为“必须是构造函数中的第一条语句此语句没有多大意义。如果您想说 this() 不能从 main 方法内部调用,那么是的,它不能是因为 main 是静态的并且不会引用这个()

答11:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

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