【问题标题】:What is the alternative to a non-static initialization block?非静态初始化块的替代方法是什么?
【发布时间】:2013-08-08 10:25:57
【问题描述】:

我的项目中有一些开发人员喜欢非静态初始化块

这个替代是什么?这个替代的缺点是什么?我猜:初始化 constructor 中的值?

我们为什么要使用非初始化块? 据我了解,“初始化块”用于在实例化类时设置值。那么构造函数还不够吗?

public class BlockTest {
    String test = new String();

    //Non-static initialization block
    {
        test = "testString";
    }
}

这个块让我感到困惑并导致可读性降低。感谢您的回复!

【问题讨论】:

    标签: java constructor initialization block non-static


    【解决方案1】:

    首先,在那里将 test 初始化为 new String() 是没有意义的,因为初始化块会立即将其分配给其他东西。总之……

    另一种方法是在声明中初始化:

    public class BlockTest {
        String test = "testString";
    }
    

    另一个在构造函数中:

    public class BlockTest {
        String test;
        public BlockTest () {
            test = "testString";
        }
    }
    

    这是两个主要的常用选项。

    初始化块有两个主要用途。第一个是在初始化期间必须执行一些逻辑的匿名类:

    new BaseClass () {
        List<String> strings = new ArrayList<String>();
        {
            strings.add("first");
            strings.add("second");
        }
    }
    

    第二个是必须在每个构造函数之前进行的通用初始化:

    public class MediocreExample {
        List<String> strings = new ArrayList<String>();
        {
            strings.add("first");
            strings.add("second");
        }
        public MediocreExample () {
            ...
        }
        public MediocreExample (int parameter) {
            ...
        }
    }        
    

    但是,在这两种情况下,都有不使用初始化块的替代方案:

    new BaseClass () {
        List<String> strings = createInitialList();
        private List<String> createInitialList () {
            List<String> a = new ArrayList<String>();
            a.add("first");
            a.add("second");
            return a;
        }
    }
    

    还有:

    public class MediocreExample {
        List<String> strings;
        private void initialize () {
            strings = new List<String>();
            strings.add("first");
            strings.add("second");
        }
        public MediocreExample () {
            initialize();
            ...
        }
        public MediocreExample (int parameter) {
            initialize();
            ...
        }
    }        
    

    有很多方法可以做这些事情,使用最合适的方法并提供最清晰和最易于维护的代码。

    【讨论】:

    • +1 用于涵盖值得考虑的替代方案。
    • 在那里初始化字符串没有意义是正确的,但这只是为了示例目的;-)
    【解决方案2】:

    编译器将非静态初始化块插入到每个构造函数中。初始化实例字段所需的代码也插入到每个构造函数中。这个

    class Test1 {
        int x = 1;
        {
            x = 2;
        }
        Test1() {
            x = 3;
        }
    }
    

    编译成与此相同的字节码

    class Test1 {
        int x;
        Test1() {
            x = 1;
            x = 2;
            x = 3;
        }
    }
    

    【讨论】:

    • 这可能是真的,但问题的本质是围绕语法和可观察行为,而不是编译后的等效字节码。 +1 用于清楚地说明初始化的顺序(即使这不一定是您的目标)。
    【解决方案3】:

    初始化块别无选择,实际上是构造函数的替代。

    public TestClass {
            TestClass() {
    
            }
        }
    

    这在匿名类的情况下很有用,因为你不能有一个构造函数,原因很简单,你没有类的名称,那么你就不能有构造函数,否则会发生什么你的名字。

    new MyClass(){
       //its an anonymous class, you can't use constructor here
          {
          }
      }
    

    但是你可以用你的声明来初始化变量,比如

    public TestClass {
        String test = "value";
    }
    

    但这不是一种选择,因为你不能以这种方式执行任何操作(比如算术或字符串操作),但你可以在初始化块中执行

    public TestClass {
            String test = "value";
            test = test + " not found"//compiler error
            {
             test = test + " not found" // valid
            }
        }
    

    【讨论】:

    • 如果您只是分配值,您可以初始化声明它们的字段。
    • 另请注意,在所有情况下,都可以在不使用非静态初始化块的情况下进行重写。并不是你一直想要的,它可以是一个非常方便的构造。但“初始化块别无选择”的说法并不完全正确。
    猜你喜欢
    • 2013-08-08
    • 2010-09-25
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 2011-01-26
    • 1970-01-01
    相关资源
    最近更新 更多