有一段代码看起来像这样。问题是在启动期间发生了 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()
是完全可以的。在一段时间内,只要以一致的方式完成(这完全是另一个主题)。
另请参阅
-
Object.hashCode()
-- 确保您了解契约(Contract)的含义
在 cache
是static
更多信息重新出现,我们现在知道相关对象虽然可变,但不 @Override hashCode()
。然而,在制作cache
的设计中似乎存在一个严重问题。一个static
ForumRepository
领域类,具有非 static
“二传手”setCacheEngine
(看起来是由 Cacheable
指定的)。
这意味着只有 cache
的化身,无论有多少ForumRepository
实例已创建!在某种程度上,所有实例ForumRepository
“共享”相同 cache
!
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. Astatic
field, sometimes called a class variable, is incarnated when the class is initialized.
我认为现在退后一步并提出以下问题很重要:
- 是
cache
需要static
?这是故意的吗?- 应该
ForumRepository
的实例有自己的cache
? - ...或者他们都应该“共享”相同的
cache
?
- 应该
ForumRepository
有多少个实例将被创建?- 抛开设计模式的优缺点,应该
ForumRepository
是单例吗?
- 抛开设计模式的优缺点,应该
- 可以
setCacheEngine
多少次被称为ForumRepository
目的?- 它会受益于 throw 的防御机制
IllegalStateException
如果它被多次调用?
- 它会受益于 throw 的防御机制
最佳建议取决于上述问题的答案。第三个要点是可以立即采取行动的,并且会显示 setCacheEngine
被多次调用。即使它们只为每个 ForumRepository
调用一次例如,在当前的事态中,它实际上仍然是一个多重“集合”,因为只有一个 cache
.
一个static
具有非 static
的字段setter 是一个需要彻底重新检查的设计决策。
关于java - 成员变量的hashCode()值不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2797340/