在Java中比较引用两个具有相同值的字符

时间:2016-05-08 02:21:56

标签: java memory jvm

我们知道Java中的运行时常量池存储以下文字: 1)整数2)长3)浮点数4)双5)字符串。因此,存储的布尔文字和字符文字在哪里?

示例:

Character c1 = 'a';
Character c2 = 'a';
System.out.println(c1==c2); //prints true

由于==比较引用,c1和c2是否共享相同的引用? (=请注意,创建这些文字使得它们是相应的原始包装类的对象。

3 个答案:

答案 0 :(得分:2)

正如你所说,c1和c2在堆中共享相同的对象,因此比较将为真。这是Java缓存机制。将缓存在-127 .. 127范围内值的所有字符,整数。因此Java将获得缓存值而不是创建新值。这就是两个对象共享相同引用的原因。

Character c1 = 'a';
Character c2 = 'a';  
Character c3 = new Character('a');  // force Java creates new object in heap 
System.out.println(c1 == c2); -> true 
System.out.println(c1 == c3); -> false

出于同样的原因,这是另一个例子:

Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2);  // true
Integer i3 = 1000;
Integer i4 = 1000;
System.out.println(i3 == i4); // false, out of cache range

您将遇到另一个字符串示例,但是在不同的机制上:

String s1 = "stack";
String s2 = "stack";
String s3 = new String("stack");
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false

创建时的所有java字符串都将分配并存储在String Pool中。当您创建新字符串时(如果是s2),Java将在String pool中搜索此字符串是否已在某处分配。在第三种情况下,我们对Java说:"嗨,Java,请随时为我创建新的"。

总结,在使用compareTo方法比较两个对象时,比较两个基元时,可以使用==运算符。 (只是提醒你旧的Java类)。

希望这有帮助:)

答案 1 :(得分:2)

  

我们知道Java中的运行时常量池存储以下文字:1)整数2)长3)浮点数4)双5)字符串。

实际上,这并不完全正确。一个正确的陈述是在实践中为每个类型BooleanByteShort,{{1}提供了一个单独的自动装箱值的运行时池},CharacterInteger

这些池不适用于文字 ...因为包装类型的文字不存在 1 。这些类型的Java文字是基本类型的值。 (事实上​​,根据JLS,类型Longbyte根本没有明显的文字。)

shortFloat没有自动装箱池,尽管各个Double方法的javadoc似乎意味着什么。 JLS不需要valueOfFloat的autobox缓存,并且库不实现它(至少在Java 6,7,8中)。

另一点需要注意的是,并非所有由自动装箱生成的值都在相应的池中。例如,(默认情况下)只有Double缓存-128到+127的值。

  

因此,布尔文字和字符文字在哪里存储?

答案如下:

  • 没有IntegerBoolean类型的文字。
  • 由自动装箱创建的CharacterBoolean的实例可能来自相应的自动装箱池。

以你的例子为例:

  

由于==比较引用,c1和c2是否共享相同的引用?

这是正确的。它说明了前一点。 Character的自动装箱池(通过JLS)需要通过Character缓存'\u0000'

请注意,我遗漏了'\u007f'String池是不同的,因为它(主要)用于字符串文字。另一方面,没有为字符串值定义自动装箱......因为字符串值不必与原语与包装二分法相抗衡。

1 - 抱歉迂腐,但是如果你想真正了解这些事情并与其他人一致地谈论这些事情,那么使用正确的Java特定术语是至关重要的。为了严格地说,Literal是出现在>>源代码中的内容<<一个程序。在运行时,相应的东西是值。

答案 2 :(得分:0)

Character c1 = 'a';
Character c2 = 'a';

一样
Character c1 = 'a';
Character c2 = c1;

两个引用指向同一个对象。在我创建的第二个案例中,c2引用c1,其中c1也是一个指向对象'a'的引用变量。

可以找到有关参考变量的更多说明here

另外更准确地说,你是在堆栈内存中创建两个引用变量,名义上是c1和c2,但它们都指向堆内存中的同一个对象!