【发布时间】:2018-01-23 14:35:47
【问题描述】:
假设我有一堂课
class A{
public final static TreeMap<String,String> tmap = new TreeMap<>();
int x;
static{
tmap.put("x:I", "Hello");
}
}
我创建了一个子类
class B extends A{
long y;
static{
tmap.put("y:J","World");
}
}
如果我现在写一些代码来检查静态初始化器:
class Main{
public static void main (String[] args){
B b = new B();
for(String v : b.tmap.values()){
System.out.println(v);
}
}
}
我知道这两个条目必须在 tmap 中,因为 A 最终必须被加载,以便最迟 B 的超级调用。
但如果我正确读取了When does static class initialization happen?,我不能假设Hello 值总是首先放入映射中,因为tmap 是最终值。
因此,如果排序很重要(例如,如果我知道某些值可能会在层次结构中进一步更新/覆盖),我是否需要删除 final 修饰符?
或者是否有其他东西已经强制执行“正确的”静态初始化程序排序?
【问题讨论】:
-
在您的示例中,添加实体的顺序并不重要,因为 TreeMap 会自动按照键的自然顺序对它们进行排序。作为此问题的示例,LinkedHashMap 可能会更好。
-
为什么你认为final跟订单有关系?
-
@SotiriosDelimanolis 因为链接到问题的答案强调静态初始化器在第一次使用 非常量 静态字段之前被调用。静态最终字段是常量。
-
如果您点击该答案中的 JLS 链接,您会发现它表示一个常量变量。
final和static类型为TreeMap的字段不是常量变量。
标签: java static classloader operator-precedence static-initializer