在使用Java时,我发现了一件相当奇怪的事情。也许这是一件普通的事情,但我不明白为什么会这样。
我有这样的代码:
Character x = 'B';
Object o = x;
System.out.println(o == 'B');
它工作正常,输出为“true”。 然后我将英语B改为slavic B(Б):
Character x = 'Б';
Object o = x;
System.out.println(o == 'Б');
现在输出为“false”。怎么会? 顺便说一句,如果我直接将x变量与'Б'进行比较,输出仍然是“真”,但是当我通过对象执行它时它的工作方式不同。
请有人解释一下这种行为吗?
答案 0 :(得分:8)
没有拳击 - 只使用char
- 你会没事的。同样,如果您使用equals
代替==
,那么您可以。问题是您正在使用==
比较盒装值的引用,Integer
只检查引用标识。由于自动拳击的工作方式,你看到了不同之处。您可以使用Object x = 0;
Object y = 0;
System.out.println(x == y); // Guaranteed to be true
Object x = 10000;
Object y = 10000;
System.out.println(x == y); // *May* be true
看到相同的内容:
int
基本上“小”值缓存了盒装表示,而“较大”值可能不缓存。
来自JLS 5.1.7:
如果被装箱的值是一个类型为
总是如此long
的整数文字,介于-128和127之间(§3.10.1),或者布尔文字为true或false(§3.10.3),或者是一个字符在'\ u0000'和'\ u007f'之间包含文字(§3.10.4),然后让a和b为p的任意两次拳击转换的结果。 a == b。理想情况下,装箱原始值总会产生相同的参考。实际上,使用现有的实现技术可能不可行。上面的规则是一种务实的妥协,要求将某些共同的值总是装入无法区分的对象中。实现可以懒惰地或急切地缓存这些。对于其他值,该规则不允许对程序员的盒装值的身份进行任何假设。这允许(但不要求)共享部分或全部这些引用。请注意,允许共享
char
类型的整数文字,但不是必需的。这确保了在大多数情况下,行为将是所需的行为,而不会造成过度的性能损失,尤其是在小型设备上。例如,较少内存限制的实现可以缓存所有
short
和int
值,以及-32K到+ 32K范围内的long
和\u0000 and
值。
关于“{{1}} \ u007f`之间的字符文字”的部分保证将缓存盒装的ASCII字符,但不保留非ASCII的盒装字符。
答案 1 :(得分:2)
当你做
时Character x = 'B'
2: invokestatic #16 // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
哪个缓存
此方法将始终将“\ u0000”范围内的值缓存到“\ u007F”(包括),并可以缓存此范围之外的其他值。
public static Character valueOf(char c) {
if(c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
<强>类似强>