我有一个单身类,如下所示:
public enum SingletonClassA {
INSTANCE;
private final Map<Character, Character> characters;
// private constructor
SingletonClassA() {
Map<Character, Character> aCharMap = new HashMap();
aCharMap.put('a', 'e');
aCharMap.put('o', 'u');
// in order to keep short I erased other puts.
characters = aCharMap;
}
public char getInstance(final char letter) {
return characters.get(letter);
}
public boolean containsKey(char letter) {
return characters.containsKey(letter);
}
}
为了测试我只创建了一个单个对象,即使我不止一次调用,我也用JUnit创建了一个测试用例:
public class SingletonTest {
@Test
public void TestSingletonObject(){
SingletonClassA instance1 = SingletonClassA.INSTANCE;
SingletonClassA instance2 = SingletonClassA.INSTANCE;
//Passes
Assert.assertSame("2 objects are same", instance1, instance2);
}
@Test
public void TestgetInstance(){
SingletonClassA instance1 = SingletonClassA.INSTANCE;
SingletonClassA instance2 = SingletonClassA.INSTANCE;
// Does not pass
Assert.assertSame(instance1.getInstance('o'), instance2.getInstance('o'));
}
}
测试从TestSingletonObject()传递,它表示这两个对象完全相同。但是从第二个,TestgetInstance(),它没有通过。
我的问题是:为什么?为什么它没有通过第二次测试。我在想,即使我调用实例方法它应该返回true,因为它们属于完全相同的对象。我错过了一点吗?
答案 0 :(得分:1)
这类似于this question。您的getInstance()
方法返回一个原语,但JUnit的Assert.assertSame(Object, Object)
需要2个对象,并检查它们的引用是否指向同一个对象。
在这种情况下,Java将使用自动装箱,实质上是调用Character.valueOf(char)
以便为assert方法提供正确的参数。但是,由于这将为每个参数创建一个单独的Character
对象,因此断言将失败。
请尝试使用Assert.assertEquals(Object, Object)
。这将使用equals(Object)
方法。
答案 1 :(得分:1)
您的代码通过了所有测试。它应该。
即使通过assertSame()
导致自动装箱,也会为char
值0-127
(包括)返回相同的对象,因为这些值为{{3 }}
这是cached
的源代码public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
其行为在其javadoc(摘录)中得到确认:
...此方法将始终缓存范围&#39; \ u0000&#39;到&#39; \ u007F&#39;,包括......
自推出以来一直保持不变(版本1.5)。
但是,如果您的代码并返回0-127范围之外的值,例如:
aCharMap.put('c', '¢'); // the "cent" char is decimal 155
然后使用它的测试将失败:
Assert.assertSame(instance1.getInstance('c'), instance2.getInstance('c')); // fails