Java:最终字段冻结对象从最终字段可达 [英] Java: Final field freeze on object reachable from final fields

查看:184
本文介绍了Java:最终字段冻结对象从最终字段可达的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标题为核心Java并发的DZone refcard说明:

DZone refcard titled "Core Java Concurrency" states:


一旦设置,最终字段值
不能更改。将对象引用字段标记为final
不会阻止从该字段引用的对象稍后更改。对于
示例,最终的ArrayList字段不能更改为不同的
ArrayList,但可以在列表实例上添加或删除对象。

Once set, final field values cannot be changed. Marking an object reference field as final does not prevent objects referenced from that field from changing later. For example, a final ArrayList field cannot be changed to a different ArrayList, but objects may be added or removed on the list instance.


最终字段冻结不仅包括对象中的最终字段,还包括所有
对象可以从这些最终字段到达。

Final field freeze includes not just the final fields in the object but also all objects reachable from those final fields.

我不完全清楚第二个语句。这是否意味着如果我有一个类型B类型的最终字段,类型B类型的,最终字段类型为整数,那么类A的实例的最终字段冻结只有在最后字段冻结<$ c后完成$ c> bc 已经发生了吗?

I am not entirely clear about the second statement. Does this mean that if I have a final field in class A of type Class B, which in turn have a final field of type Integer, then final field freeze for an instance of class A completes only after the final field freeze for b.c have already happened?

public class A{

  public final B b = new B();

}

public class B{ 

  public final Integer c = 10;

}


推荐答案


这是否意味着如果我在类B的类A中有一个最终
字段,则
的最终字段为
类型为Integer,则最终字段冻结
对于类A的实例,只有在
bc的最后一个字段冻结已经发生后才会完成

Does this mean that if I have a final field in class A of type Class B, which in turn have a final field of type Integer, then final field freeze for an instance of class A completes only after the final field freeze for b.c have already happened?


$ b b

我想我会仔细地说,最终字段冻结在这种情况下意味着,当你创建一个实例A并且安全地发布时,其他对象将永远不会看到b或c的未初始化值。

I think I would carefully say that final field freeze in this case means that when you create an instance of A and safely publish it, other objects will never see an uninitialized value for b or c.

我还会说,当你在A里面创建B的实例时,A里面的其他初始化代码永远不会看到c的未初始化的值。

I would also say that when you are creating the instance of B inside A, other initialization code inside A will never see an uninitialized value for c.

我遇到关于final字段冻结的真正问题的一个例子是一个包含一个(可变的)HashMap的类,只用于读取,在构造期间初始化: / p>

One case where I have encountered real questions around final field freeze is for example a class that contains a (mutable) HashMap, intended only for read, initialized during construction:

public class DaysOfWeek {
    private final Map daysOfWeek = new HashMap();
    public DaysOfWeek() { 
      // prepopulate my map
      daysOfWeek.put(0, "Sunday");
      daysOfWeek.put(1, "Monday");
      // etc
    }

    public String getDayName(int dayOfWeek) {
      return daysOfWeek(dayOfWeek);
    }
}

问题出现在这里: ,并且由于这里没有同步,是否安全的其他线程调用getDayName()?答案是肯定的,因为最终字段冻结保证HashMap和从它可达到的一切(这里只是字符串,但可以是任意复杂的对象)在构造结束时被冻结。 [如果你想在构建之后实际修改这个地图,那么你需要围绕读取和写入显式同步。]这是一个更长的博客,探索主题,并检查评论,以获得一些有趣的反应,如Brian Goetz。

The question arises here: assuming this object is safely published, and given that there is no synchronization here, is it safe for other threads to call getDayName()? The answer is yes, because final field freeze guarantees that the HashMap and everything reachable from it (here it's just strings, but could be arbitrarily complex objects) is frozen at the end of construction. [If you want to actually modify this map after construction, then you'll need explicit synchronization around reads and writes.] Here's a lengthier blog exploring the topic and check the comments for some interesting responses by people like Brian Goetz.

btw I是refcard的作者

btw I'm the author of the refcard

这篇关于Java:最终字段冻结对象从最终字段可达的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆