如何从另一个构造函数中调用空构造函数?

4

我有一些类似以下代码:

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

我想知道是否可能实现像这样的东西(我知道调用另一个构造函数必须是构造函数中的第一条语句)。 我在这里搜寻过但没有找到类似的内容,这让我相信也许我应该在实例化方法中处理错误逻辑。


1
你想达到什么目的?即为什么要调用一个空构造函数? - Oliver Charlesworth
1
不,你只能在构造函数中的第一次调用另一个构造函数。 - Willem Van Onsem
@WillemVanOnsem 我也这么认为,谢谢。 - Dark Star1
@OliverCharlesworth 如果对象初始化失败,我想返回一个空对象。这样我就可以简化初始化方法中的错误检查代码。 - Dark Star1
@DarkStar1:你说的空对象是什么意思? - Frank Puffer
显示剩余2条评论
4个回答

3

只需更改执行顺序:

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

1
那种方法唯一的问题是,如果在 try 部分初始化了两个或更多成员,则异常可能会在中间发生,导致一些成员具有默认值,而另一些成员具有被覆盖的值。 - Roee Gavirel

2
通常情况下,调用可能在构造函数中引发异常并完全从调用者中抑制异常不是一个好的实践。然而,你可以重构你的代码,将参数为空的构造函数的“默认”初始化移动到一个帮助方法中,然后可以从第二个构造函数的异常处理程序中调用该方法。
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;
    }
}        

2

正如你所说的

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

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

  1. Make an init function and call it from both places:

    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. Make a static function to initialize the object and return it.

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

他们为什么需要做那么多?他们已经得到了他们要求的东西,而不需要做任何事情。 - Lew Bloch
哈?如果他们已经有了他们需要的,他们就不必在这里询问了。 - Roee Gavirel
1
我猜我们中的一个人没有理解这个问题。 - Roee Gavirel

1
在构造函数的catch块中不需要执行任何操作。它应该按照您想要的方式工作。 但是,请查看此try-catch-in-constructor-recommended-practice,以选择适合您问题的正确方法。
另外,如果您正在进行任何默认初始化,请遵循@StuartLC提到的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接