初始化变量与声明或静态初始化之间有区别吗?

时间:2013-08-24 10:50:39

标签: java static coding-style

静态初始化程序由类加载器调用一次,这正是我想要的,但在静态代码块之外进行初始化更具可读性(有争议)。两者之间有区别吗?

private static final Map<MyEnum, Cheese> cheeseCache;

    static {
        parserCache = new EnumMap< MyEnum, String>(MyEnum.class){{
            for(MyEnum myEnum: MyEnum.values()){
                put(myEnum, new Cheese(myEnum)) ;
            }

        }};
    }

或者这个:

private static final Map<Lab, LabResultParser> cheeseCache 
        = new EnumMap< MyEnum, String>(MyEnum.class){{
            for(MyEnum myEnum: MyEnum.values()){
                put(myEnum, new Cheese(myEnum)) ;
            }
        }};

3 个答案:

答案 0 :(得分:3)

它会影响排序 - 例如你可以:

private static final int declaredFirst;

private static final int declaredSecond = new Random.nextInt();

static {
    declaredFirst = declaredSecond + 1;
}

初始化程序以文本顺序执行。当然,您可能刚刚宣布declaredFirst秒:

private static final int declaredSecond = new Random.nextInt();
private static final int declaredFirst = declaredSecond + 1;

我个人使用静态初始化块,我无法在单个表达式中干净地表达初始值。

哦,如果在静态初始化块中初始化,则不能将变量视为常量表达式:

private static final int THIS_IS_A_CONSTANT = 10;
private static final int thisIsNotAConstant;

static {
    thisIsNotAConstant = 20;
}

public static void main(String[] args) {
    System.out.println(THIS_IS_A_CONSTANT); // 10 is inlined
    System.out.println(thisIsNotAConstant); // 20 is not inlined
}

当然,这只是很少相关。

所以在大多数案例中,这只是个人选择。当然在你的情况下,使用更多语句的能力意味着你需要使用丑陋的(IMO)“匿名内部类来获得一些初始化”:

private static final Map<MyEnum, Cheese> cheeseCache;

static {
    parserCache = new EnumMap<>(MyEnum.class);
    for (MyEnum myEnum: MyEnum.values()) {
        put(myEnum, new Cheese(myEnum));
    }
}

答案 1 :(得分:1)

为了初始化,两个片段都会创建一个扩展EnumMap的匿名内部类。简单地委托给一个方法会更简洁:

private static final Map<MyEnum, Cheese> CHEESE_CACHE = createCheeseCache();

private static Map<MyEnum, Cheese> createCheeseCache() {
    EnumMap<MyEnum, Cheese> result = new EnumMap<MyEnum, Cheese>(MyEnum.class);
    for (MyEnum myEnum: MyEnum.values()){
       result.put(myEnum, new Cheese(myEnum)) ;
    }
    return result;
}

答案 2 :(得分:0)

在你的情况下没有区别,因为你没有做任何逻辑来决定应该为静态变量分配什么值。

来自java tutorial

  

声明中字段的初始化值适用于   初始化值可用,初始化可以   放在一条线上。但是,这种初始化形式存在局限性   因为它的简单。如果初始化需要一些逻辑(for   例如,错误处理或for循环来填充复杂的数组),简单   任务不充分。实例变量可以初始化   构造函数,可以使用错误处理或其他逻辑。至   为类变量提供相同的功能,即Java编程   语言包括静态初始化块。

但我会使用静态块,因为如果需要,您还可以选择try/catch中的初始化代码。假设在填充enumMap时出现问题的情况,如果异常在逻辑上不是致命的,我可能仍希望继续执行。