不使用this()的构造函数链式调用

5

我理解构造函数链是从最小的构造函数到最大的构造函数。例如

    public MyChaining(){
        System.out.println("In default constructor...");
    }
    public MyChaining(int i){
        this();
        System.out.println("In single parameter constructor...");
    }
    public MyChaining(int i,int j){
        this(j);
        System.out.println("In double parameter constructor...");
    }

我理解到调用 this()super() 的语句必须在第一行。但是是否有可能(如果可以的话,是否有效)绕过这个限制,从而链接不同的构造函数呢?
例如,我有这两个共享一些代码的构造函数。
    public Location(String _Name) throws IOException, JSONException {
        //Three lines of unique code (must be executed before the shared code)
        //Shared code
    }

    public Location(JSONObject json) {
        //Shared code
    }

第一个构造函数是否有可能调用第二个构造函数?

@Philipp 是的,它会被完成。我只是想知道是否可以通过链接来完成,因为我在其他地方找不到答案。 - Akaitenshi
4个回答

4
当然,如果你有一个静态函数 static function

JSONObject foo(String)

那么你可以这样写:

public Location(String _Name) throws IOException, JSONException {
    this(foo(_Name));
}

3
唯一的方法在不调用this的情况下运行共享代码是,两个构造函数都调用一个包含共享代码的初始化方法。
public Location(String _Name) throws IOException, JSONException {
    //Three lines of unique code (must be executed before the shared code)
    init ();
}

public Location(JSONObject json) {
    init (); // perhaps the JSONObject should be passed to that method, otherwise
             // that parameter is useless. On the other hand, I don't see a
             // JSONObject in the other constructor
}

private void init () {
    // shared code
}

是的,我知道可以这样做。我想知道是否可以仅通过链接完成。 - Akaitenshi
1
init()方法还有另一个困难。你不能在该方法中初始化final实例字段。 - A. Sundararajan
@Akaitenshi 链式操作仅能使用 this();,并且必须是构造函数的第一行。 - Eran
@Eran 好的,谢谢。共享代码实际上是JSON解析,因此其中没有最终字段。第一个构造函数调用一个读取方法,该方法从URL获取JSON。第二个构造函数直接从其他类获取JSON。 - Akaitenshi

1
一个略有不同的答案:不要这样做。
构造函数与你类中的任何其他成员一样,它们应该在“整体上”是有意义的。拥有提供完全“不同”或“独立”的“接口”给用户的构造函数看起来对我来说像是代码异味。
你看,如果你能在你的类中“画”一条线,并发现一些元素总是在那条线的左侧,而许多其他元素则在右侧,那么这表明也许你应该沿着那条“线”分割你的类,并创建两个类。
如果你真的想从不同的上下文中创建相同类型的对象,则尝试识别“共同分母X”,并为该X提供一个构造函数。然后使用工厂方法,可能以不同的方式使用该共同构造函数。这意味着你可以在同一个类中提供静态方法,例如
static Location generateLocationFromFoo(Foo foo) { ... }
static Location generateLocationFromBar(Bar bar) { ... }

或者更进一步,创建一个单独的工厂类,用于为您生成实际的位置对象。

抱歉,我不完全理解你上一句话的意思。你是指我可以从同一个类中的方法调用构造函数并使用该方法来实例化我的对象吗? - Akaitenshi
更新了答案;希望有所帮助。 - GhostCat
所以我会在 generateLocation 中调用构造函数,并在主函数中或者需要对象时调用 objName.generateLocation() - Akaitenshi

1
我认为从最小构造函数到最大模式的链接方式很难阅读,因为实际构造函数逻辑分散在许多不同的方法中。
我认为最易读的方式是:
- 有一个“主”构造函数,完全处理实例初始化 - 所有其他构造函数都调用它
此外,我有些不喜欢长链式(从简单的构造函数下钻很难找到实际代码),所以我倾向于编写所有其他构造函数直接调用“主”函数,除非这意味着重复代码。
您始终可以通过调用静态方法来避免“this()”必须是第一条语句的限制,除非您尝试做一些实际上正在尝试防止使用半初始化对象的规则(例如使用半初始化对象)。请注意,被调用的函数必须是静态的,以确保防止使用半初始化对象。

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