【问题标题】:Init block VS init() private method called in constructor在构造函数中调用的初始化块 VS init() 私有方法
【发布时间】:2014-04-29 03:46:24
【问题描述】:

我知道有几种方法可以在 Java 中创建实例时初始化内容,但我对以下两种可能性之间的区别感兴趣。

案例一:

{
    // common init code for all constructors
}

public MyType() {
    super();
    // specific init code
}

public MyType(Object arg) {
    super(arg);
    // specific init code
}

案例 2:

public MyType() {
    super();
    init();
    // specific init code
}

public MyType(Object arg) {
    super(arg);
    init();
    // specific init code
}

private void init() {
    // common init code for all constructors
}

我相信这两种情况在代码方面是等价的。我认为第一个更快,因为方法调用少了 1 个,但另一方面,对于那些对初始化不太了解的人来说,这可能会让人感到困惑。

是否还有我错过的另一个差异可能导致我们选择一个而不是另一个? 我应该首选哪个选项?

注意: init() 方法是私有的,我知道不同的可见性可能会导致初始化错误(子类化时),这不是重点。

【问题讨论】:

    标签: java initialization


    【解决方案1】:

    也许第一个更快,因为方法调用少了 1 个,但我认为它的可读性较差。

    我什至不会在这里考虑效率,因为它只会对方法调用产生微小的影响。但是为什么你认为它的可读性较差?这是 Java 语言的一个众所周知的特性。

    我应该首选哪个选项?

    第一种方法的好处是,您可以编写更少的代码。在第二种方法中,人为错误的可能性很小。通常,当您希望在每个构造函数中完成初始化时,您会使用实例初始化程序块。这使您无需在所有构造函数中显式编写相同的代码。对于另一种方法,您必须记住从所有构造函数中调用init() 方法。

    但是,如果您希望某些初始化成为某个构造函数的一部分,那么第二种方法可能会很有用。但这在 IMO 中非常罕见。

    【讨论】:

    • 我觉得它的可读性很好,但是我遇到过很多不了解这个非静态 init 块的 Java 程序员,所以我才这么说。
    • @Joffrey 那么在这种情况下,他们会学到一些他们不知道但应该知道的东西。
    【解决方案2】:

    简而言之,第一种情况下的初始化代码将在构造函数之前调用,在第二种情况下 - 之后。 看看这个question

    一般规则是避免使用像 theese 这样的结构,而是使用static-factory-methods

    顺序可能很重要,然后调用 this() 而不是 super(): 考虑代码:

    public class InitOrderTest {
    static class Super {
        Super() {
            System.out.println("Super constructor");
        }
    }
    static class Puper extends Super {
        {
            System.out.println("Code block");
        }
        Puper() {
            this("Self constructor");
            init();
        }
    
        public Puper(String inner) {
            System.out.println(inner);
        }
    
        private void init() {
            System.out.println("Init call");
        }
    }
    public static void main(String[] args) {
       new Puper();
    }
    

    }

    打印出来:

    Super constructor
    Code block
    Self constructor
    Init call
    

    【讨论】:

    • init 代码在第一种情况下将在构造函数之前调用,在第二种情况下 - 在之后这取决于您调用init() 的位置。但是 init 块之前并没有真正调用,它是在 super() 调用之后立即调用的。
    • 第一种情况下的初始化代码将在构造函数之前调用 - 不,情况并非如此。两个代码的功能完全一样。
    • @theme 无论如何,感谢您指出静态工厂方法。
    猜你喜欢
    • 2014-06-08
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多