2013-08-07 59 views
6

我的项目有一些开发人员喜欢非静态初始化块什么是非静态初始化块的替代方案?

什么是替代这个,什么是缺点这种替代的?我猜想:初始化构造函数中的值?

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

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

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

该块使我感到困惑,导致可读性下降。感谢您的答复!

+0

构造.. – Ankit

回答

10

首先,这样做,这是没有意义的初始化测试一个新的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(); 
     ... 
    } 
}   

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

+0

+1用于涵盖其他值得考虑的情况。 – kiheru

+0

在这里初始化字符串没有任何意义,但这仅仅是为了示例目的;-) –

2

初始化块没有其他选择,实际上它是构造函数的替代方案。

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

可以初始化他们声明,如果你只是分配值的字段。 –

+1

@JasonC请参阅我的编辑 – Ankit

+0

还要注意,在所有情况下都有一种方法可以在不使用非静态初始化块的情况下进行重写。不是你一直想要的,它可以是一个非常方便的构造。但“初始化块没有其他选择”并不完全正确。 –

6

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

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

编译成相同bytecoode因为这

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

这可能是正确的,但问题的本质围绕语法和可观察行为,而不是等同的字节代码汇编。 +1,以清楚地说明初始化的顺序(尽管它不一定是你的目标)。 –