Java。为什么它与英语和斯拉夫语字符有所不同?

Java。为什么它与英语和斯拉夫语字符有所不同?

问题描述:

我在使用Java时发现了一个很奇怪的事情。也许这是一件普通的事情,但我不明白为什么它以这种方式工作。Java。为什么它与英语和斯拉夫语字符有所不同?

我有这样的代码:

Character x = 'B'; 
Object o = x; 
System.out.println(o == 'B'); 

它工作正常,输出为“真”。 然后我改变英语B至斯拉夫B(Б):

Character x = 'Б'; 
Object o = x; 
System.out.println(o == 'Б'); 

现在的输出为 “假”。怎么来的? 顺便说一下,如果我直接将x变量与'Б'进行比较,那么输出结果仍然是“真”,但是当我通过对象执行时,它的工作方式不同。

任何人都可以解释这种行为吗?

没有拳击 - 只使用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 

基本上都是“小”值已缓存的盒装表示,而“较大”的值可能不是。

JLS 5.1.7

如果值p被装箱是-128到127之间的字面int类型的整数包容(§3.10.1)或布尔值真或假(§3.10。 3)或'\ u0000'和'\ u007f'之间的字符字面值(§3.10.4),则让a和b为p的任意两次装箱转换的结果。情况总是如此,a == b。

理想情况下,装箱原始值总是会产生相同的参考。实际上,使用现有的实现技术可能不可行。上述规则是一种务实的妥协,要求某些共同的价值观总是被装箱成不可区分的对象。实现可能会缓存这些,懒惰或热切。对于其他值,该规则不允许对程序员的盒装值的身份进行任何假设。这允许(但不要求)共享这些引用的一部分或全部。请注意,允许共享long类型的整数文字,但不是必需的。

这可以确保在大多数情况下,行为将成为所需的行为,而不会对性能造成不必要的损失,特别是在小型设备上。例如,较少的内存有限的实现可能会缓存所有值为-32K到+ 32K的所有charshort值,以及intlong值。

关于“\u0000 and \ u007f`之间的字符文字”的部分保证了盒装ASCII字符将被缓存,但不是非ASCII盒装字符。

当你做

Character x = 'B' 

它调用Character.valueOf(C)

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); 
} 

类似