java - 成员变量的hashCode()值不同

标签 java multithreading

有一段代码看起来像这样。问题是在启动期间发生了 2 次初始化。 (1) 某些方法对 ForumRepository 进行反射并执行 newInstance() 纯粹是为了调用 #setCacheEngine。 (2) 接下来的另一个方法调用#start()。我注意到,在一些奇怪的场景中,#cache 成员变量的 hashCode 有时会有所不同。由于只有 1 段代码调用 #setCacheEngine,那么 hashCode 在运行时如何改变(我假设不同的实例将具有不同的 hashCode)。这里有什么地方有错误吗?

public class ForumRepository implements Cacheable
{
    private static CacheEngine cache;
    private static ForumRepository instance;

    public void setCacheEngine(CacheEngine engine) { cache = engine; }

    public synchronized static void start()
    {
        instance = new ForumRepository();
    }

    public synchronized static void addForum( ... )
    {
        cache.add( .. );
        System.out.println( cache.hashCode() );
        // snipped
    }

    public synchronized static void getForum( ... )
    {
        ... cache.get( .. );
        System.out.println( cache.hashCode() );
        // snipped
    }
}

整个系统在 servlet 的 init 方法中连接和初始化。 init() 方法在概念上看起来像这样:

// create an instance of the DefaultCacheEngine
cache = (CacheEngine)Class.forName( "com..DefaultCacheEngine" ).newInstance();
cache.init();

// init the ForumRepository's static member
Object o = Class.forName( "com.jforum....ForumRepository" ).newInstance();     
if( o instanceof Cacheable )
    ((Cacheable)o).setCacheEngine(cache);

// Now start the ForumRepository
ForumRepository.start();

更新这段代码不是我写的。取自jforum

更新 2 已找到解决方案。我在下面添加了一条单独的评论来描述问题的原因。谢谢大家。

最佳答案

您必须提供比这更多的信息,但是 CacheEngine可能是一种可变的数据类型,更糟糕的是,它甚至可能被其他人共享。取决于如何CacheEngine定义其 hashCode() ,这很可能导致aForumRepository从其 cache 中看到各种不同的哈希码.

对于同一个对象来说,如果它是可变的,那么改变它的 hashCode() 是完全可以的。在一段时间内,只要以一致的方式完成(这完全是另一个主题)。

另请参阅

<小时/>

cachestatic

更多信息重新出现,我们现在知道相关对象虽然可变,但不 @Override hashCode() 。然而,在制作cache的设计中似乎存在一个严重问题。一个static ForumRepository领域类,具有非 static “二传手”setCacheEngine (看起来是由 Cacheable 指定的)。

这意味着只有 cache 的化身,无论有多少ForumRepository实例已创建!在某种程度上,所有实例ForumRepository “共享”相同 cache !

JLS 8.3.1.1 static Fields

If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized.

我认为现在退后一步并提出以下问题很重要:

  • cache需要static ?这是故意的吗?
    • 应该 ForumRepository 的实例有自己的cache
    • ...或者他们都应该“共享”相同的 cache
  • ForumRepository 有多少个实例将被创建?
    • 抛开设计模式的优缺点,应该ForumRepository是单例吗?
  • 可以setCacheEngine多少次被称为ForumRepository目的?
    • 它会受益于 throw 的防御机制 IllegalStateException如果它被多次调用?

最佳建议取决于上述问题的答案。第三个要点是可以立即采取行动的,并且会显示 setCacheEngine被多次调用。即使它们只为每个 ForumRepository 调用一次例如,在当前的事态中,它实际上仍然是一个多重“集合”,因为只有一个 cache .

一个static具有非 static 的字段setter 是一个需要彻底重新检查的设计决策。

关于java - 成员变量的hashCode()值不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2797340/

相关文章:

ruby-on-rails - Rails、ActionController::Live、Puma:ThreadError

java - CompareTo() 方法如何工作 ArrayList 排序

java - 如何正确配置此 WSO2 计划任务以执行简单的 REST 服务调用?

java - Jackson 将空白字符串转换为 null

"SELECT ... FOR UPDATE"上的 Mysql 死锁并插入

objective-c - Cocoa Touch 线程问题

ios - 如何在swift中使用后台线程?

java - 搜索栏无法正常工作

javascript - 我如何从 Android 中的 cordova 插件获取返回值?

java - 如何设置运行正则表达式的java函数的时间限制