如何避免代码重复初始化最终属性?

时间:2010-03-31 19:25:20

标签: java constructor final

public class Code{

//many properties
//...

final String NEWLINE;// ohh a final property!

void creation() //this method is for avoid repetition of code
{        

    //final initialization can't be put here =(

    Source= new StringBuffer();

   //many other commons new's ..
   //...
}

Code()
{
    NEWLINE = System.getProperty("line.separator");
    creation();
}

Code(String name, int numberr)
{
    NEWLINE = System.getProperty("line.separator");
    creation();

    name=new Someting(name);
    number = new Magic(number);
}

}

5 个答案:

答案 0 :(得分:6)

编译器将所有初始值设定项添加到每个构造函数的开头。这包括:

  • 实例变量初始化
  • 初始化块{ .. }

因此,您不必将其包含在任何地方,只需将其作为实例变量初始化:

private final String NEWLINE = System.getProperty("line.separator");

或在初始化块中:

{
     NEWLINE = System.getProperty("line.separator");
}

当然,在这个精确的示例中,您应该创建字段static

答案 1 :(得分:6)

这是您的代码,有4种不同的方法来初始化最终变量。

  1. 内联
  2. 匿名初始化程序块
  3. 在构造函数中初始化
  4. 显式调用默认构造函数
  5. 结果输出如下所示。

    public class Code {
    
        // many properties
        private String name;
        private String number;
        // ...
    
        // 1.
        final String NEWLINE_1 = "1" + System.getProperty("line.separator");
        final String NEWLINE_2;
        final String NEWLINE_3;
    
        // 2.
        {
            System.out.println("initializer block invoked before Constructor");
    
            NEWLINE_2 = "2" + System.getProperty("line.separator");
            // final initialization CAN be put here =(
    
            // Source = new StringBuffer();
    
            // many other commons new's ..
            // ...
        }
    
        Code() {
            System.out.println("default constructor");
            // NEWLINE_1 = "error";     can't do this
            // NEWLINE_2 = "error";     can't do this
    
            // 3.
            NEWLINE_3 = "3" + System.getProperty("line.separator");
        }
    
        Code(String name, int number) {
            // 4.
            this();
            System.out.println("constructor(name, number)");
    
            name = new String("Someting(name)");
            this.number = new String("Magic(number)");
        }
    
        public static void main(String[] args) {
            Code code_1 = new Code();
            System.out.println(code_1.NEWLINE_1 + ":" + code_1.NEWLINE_2 + ":" + code_1.NEWLINE_3);
    
            Code code_2 = new Code("crowne", 2);
            System.out.println(code_2.NEWLINE_1 + ":" + code_2.NEWLINE_2 + ":" + code_2.NEWLINE_3);
        }
    }
    

    initializer block invoked before Constructor
    default constructor
    1
    :2
    :3
    
    initializer block invoked before Constructor
    default constructor
    constructor(name, number)
    1
    :2
    :3
    

答案 2 :(得分:3)

只是做:

final String NEWLINE = System.getProperty("line.separator");

请参阅:JLS 8.3.2. Initialization of Fields

另请参阅:JLS 12.5 Creation of New Class Instances执行顺序。

答案 3 :(得分:1)

如果每次都以相同的方式初始化它们,则可以将代码放在构造函数之外。 Java允许您这样做:

final String NEWLINE = System.getProperty("line.separator");

除了无参数之外,您还可以使用除无参数构造函数之外的所有构造函数。例如:

Code(String name, int number)
{
    this();

    name=new Someting(name);
    number = new Magic(number);
}

答案 4 :(得分:1)

另外,如果初始化很复杂并且您必须在构造期间执行此操作,请提供静态方法以返回结果,如:

Code()
{
    NEWLINE = newLineValue();
    creation();
}

Code(String name, int number)
{
    NEWLINE = newLineValue();
    creation();

    name = new Something(name);
    number = new Magic(number);
}

private static String newLineValue()
{
    return System.getProperty("line.separator");
}

在这种情况下,newLineValue()是微不足道的,所以我不会在这里使用它,但如果这实际上有大量的工作,那么它可能是有用的。您也可以从构造函数传递参数。