【问题标题】:How to call an empty constructor from another?如何从另一个调用空构造函数?
【发布时间】:2017-11-28 11:24:49
【问题描述】:

我有一些这样的代码:

public class Foo {
    private int x;

    public Foo() {
    }

    public Foo(int x) {
        try {
            //do some initialisation stuff like:
            this.x = x;
        }
        catch(Exception ge){
            //call empty constructor not possible
            //this();
            //this.EMPTY();
            //Foo();
        }
    }

    public static final Foo EMPTY = new Foo();
}

我想知道是否有可能实现这样的事情(我知道调用另一个构造函数必须是构造函数中的第一条语句)。 我在 SO 上环顾四周,但没有发现任何类似的东西,这让我相信,也许,我应该在实例化方法中处理错误逻辑。

【问题讨论】:

  • 你想达到什么目的?即你为什么要调用一个空的构造函数?
  • 不行,你只能在构造函数中调用另一个构造函数作为 first 调用。
  • @WillemVanOnsem 非常感谢。
  • @OliverCharlesworth 如果对象初始化失败,我想返回一个空对象。这样我可以简化初始化方法中的错误检查代码
  • @DarkStar1:空对象是什么意思?

标签: java constructor


【解决方案1】:

只需更改执行顺序:

public class Foo {

    Integer i;
    public Foo() {
        System.out.println("Empty constructor invoked");
    }

    public Foo(Integer i) {

        this(); //can be omitted

        try {
            System.out.println("i initialized to : "+i.toString());

        } catch (Exception ex) {

            System.out.println("i NOT initialized ");
        }
    }


    public static void main(String[] args) {

        new Foo(); //prints: Empty constructor invoked

        new Foo(5);//prints: Empty constructor invoked
                   //prints: i initialized to : 5

        new Foo(null);//prints: Empty constructor invoked
                   //prints: i NOT initialized 
    }
}

【讨论】:

  • 这种方法的唯一问题是,如果在try 部分他初始化了 2 个或更多成员。异常可能发生在中间,使一些成员具有默认值,而另一些成员具有覆盖值。
【解决方案2】:

一般来说,调用可以throw in a constructor 的代码并不是很好的做法,更糟糕的是,完全抑制来自调用者的异常。但是,您可以做的是重构代码,以便将无参数构造函数的“默认”初始化移动到辅助方法中,然后您可以在第二个构造函数中从异常处理程序中调用该方法:

public class Foo {
    private int x;

    public Foo() {
      doDefaultInitialize();
    }

    public Foo(int x) {
        try {
          // dodgy code which could throw
        }
        catch(Exception ge){
          doDefaultInitialize();        
        }
    }

    private void doDefaultInitialize() {
       // Fallback initialization goes here
       x = 42;
    }
}        

【讨论】:

    【解决方案3】:

    如你所说

    调用另一个构造函数必须是第一个语句 构造函数

    当我需要这种行为时,我通常使用两种解决方案:

    1. 创建一个初始化函数并从两个地方调用它:

      public class Foo {
          private int x;
      
          public Foo() {
              init();
          }
      
          public Foo(int x) {
              try {
                  //do some initialisation stuff like:
                  this.x = x;
              }
              catch(Exception ge){
                  init();
              }
          }
      
          private init() {
              //Do the default initialization here...
          }
      
          public static final Foo EMPTY = new Foo();
      }
      
    2. 制作一个静态函数来初始化对象并返回它。

      public class Foo {
          private int x;
      
          private Foo() {
              this.x = 42;
          }
      
          private Foo(int x) throws Exception {
              //do some initialization stuff like:
              this.x = x;
          }
      
          public static Foo getNewInstance(int x) {
              try {
                  return new Foo(x);
              } catch (Exception e) {
                  return new Foo();
              }
          }
      
          public static final Foo EMPTY = getNewInstance();
      }
      

    【讨论】:

    • 为什么他们需要做这一切?他们已经得到了他们想要的东西,而无需做任何该死的事情。
    • 哈?如果他们有他们需要的东西,他们就不必在这里问了。
    • 我猜你或我没有理解这个问题。
    【解决方案4】:

    在构造函数的 catch 块中什么都不做。它应该可以按您的意愿工作。 但是,请查看此try-catch-in-constructor-recommended-practice 以选择正确的方法来解决您的问题。

    另外,如果您正在执行任何默认初始化,请遵循@StuartLC 提到的方法

    【讨论】:

      猜你喜欢
      • 2011-03-24
      • 2010-09-22
      • 1970-01-01
      • 2020-03-14
      • 2017-01-05
      • 1970-01-01
      相关资源
      最近更新 更多