Java 将原语与行为未知的==包装器对象进行比较

Java 将原语与行为未知的==包装器对象进行比较,java,equals,equality,boxing,Java,Equals,Equality,Boxing,我有一段代码需要理解: public static void main(String[] args) { Character c = new Character('a'); Character cy = new Character('a'); char cx = 'a'; System.out.println(c == cx); System.out.println(cx == cy); System.out.println(c == cy);

我有一段代码需要理解:

public static void main(String[] args) {
    Character c = new Character('a');
    Character cy = new Character('a');
    char cx = 'a';

    System.out.println(c == cx);
    System.out.println(cx == cy);
    System.out.println(c == cy);
}
输出:

true
true
false
我无法理解为什么只有第三种说法是失败的


编辑:此问题与
不同。equals
vs
=
问题是关于原语与对象比较的问题。

c
cy
引用
字符
类的不同实例(每次调用构造函数时,都创建一个新实例),因此,比较这些引用将返回
false

另一方面,当您将它们中的任何一个与原语
cx
进行比较时,它们将被取消绑定到
char
,并且
char
比较返回true

如果使用
Character.valueOf('a')
而不是
new Character('a')
,则在两个调用中都会得到相同的实例,并且引用比较将返回
true
(因为
valueOf
在参数为 因为一个是基元,另一个是它的包装类,并且基元比较发生(=)

鉴于:

 System.out.println(c == cy);
是一个对象比较。正在比较不同的实例,因此在这种情况下,
=
将不起作用。

类不是单例,因此在调用构造函数时始终会创建一个新对象,新对象引用各自的引用。因此
(c==cy)
给你假

很明显,为什么最后一次比较会给
:两个
字符都显式初始化为
,因此是不同的对象

然而,前两次比较给出
true
的原因只是部分清楚:
char
值肯定用于检索预存储的
字符
实例,但我不知道预定义的
字符
对象到底是如何映射到此预存储实例的


不过,我希望它的工作原理类似于
字符串
对象的“==”-比较:如果在编译时比较的实例中有一个是预先存储的
字符
,那么编译器会插入对
equals()
的调用,替换“==”-比较

这部分Java非常混乱(不仅仅是)不幸的是,对于初学者来说。由于Java 5有自动装箱,它试图提供帮助,但使
=
的行为变得更加棘手。在自动装箱之前,我相信编译器会拒绝前两个比较。请注意
Character a=Character.valueOf('a'))
可以缩短为
字符a='a'
,即使
valueOf
也会返回非ASCII字符不相等的实例。好的IDE可以配置为在装箱和拆箱时发出警告,就像这里一样。@Thilo我没有看到任何自动装箱问题,只有自动拆箱。为什么其他两个c比较给我们提供了真实的结果,那么?@Thilo对于其他比较(包括原语)装箱和自动装箱将发生,即使对于单例,每次调用构造函数都会创建一个新实例。只是调用构造函数变得更加困难。是的,这就是模式试图实现的。不过,它们的构造函数在任何方面都不是特别的(除了它有私有修饰符),如果你第二次调用构造函数,你会得到一个单独的实例。@SparK as is Singleton-这与问题无关。不完全是这样,char原语到对象的匹配工作正常,而对象到对象的匹配不正常……所以我想知道为什么
new object()==new object()
false?“这个问题与.equals vs==问题不同,因为这是关于原语与对象比较的问题。”不,事实并非如此,因为理解这种差异自然可以解释这一点。
==
进行引用比较;一旦你认识到这一点,答案就无关紧要了。另请参见@jpmc26,但这是错误的。
c
是一个引用,但
c==cx
不进行引用比较。问题不一样。问题是o相反(正如其他人已经正确解释的):
如果相等运算符的操作数都是数字类型,或者一个是数字类型,另一个可转换为数字类型(§5.1.8),则对操作数执行二进制数字升级(§5.6.2)。请注意,二进制数字升级执行值集转换(§5.1.13)并且可以执行取消装箱转换(§5.1.8)。
因此发生的是取消装箱,而不是装箱。char值根本不是(“确定的”)用于检索字符实例-相反,
==
的另一面被转换为基本字符。并且编译器从不将
==
替换为等于。不用于字符串对象,不用于字符对象,不用于任何类型的对象。但是为什么对于字符串,
=
的行为与
等于()
?这不能是数组解装箱,那样会再次进行ref比较,而且据我所知,操作符不能作为本地人继续执行。。。
 System.out.println(c == cy);