class 的两个对象是否引用相同的内存位置?

Do two objects of a class refer to the same memory location?

我开始学习一些东西 Java 并且我已经阅读了很多关于 JVM 如何分配内存以及如何使用垃圾收集器释放内存的文章。

有一件事我一直无法找到,如果我创建两个完全相同的新对象,它们会指向内存中的相同位置吗?类似于字符串池的工作方式。

不,它们不是同一个对象。您可以使用 == 操作来验证这一点,该操作检查两个引用是否指向同一个对象。

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);

这将打印 false,这就是为什么您通常不想将 Strings(或者实际上,任何对象)与 == 进行比较的确切原因(ref this post). The correct way to check for (content) equality is equals(Object that).

如果您使用 new 运算符创建新对象,则可以保证它是不同于之前存在的任何其他对象的新对象。但是,当您以间接方式创建对象时(例如,使用工厂方法),之前存在的对象可能会被重用。一个很好的例子是 Integer.valueOf(int) 缓存小数字和 returns 相同实例的方法:

Integer a = Integer.valueOf(10);
Integer b = Integer.valueOf(10);
// a and b is the same object
Integer c = new Integer(10);
Integer d = new Integer(10);
// c and d are two distinct objects

请注意,即使 JVM 可以确定两个新对象在本质上是相同的,它也无法将它们合并为单个对象,因为这会违反语言规范并可能在以后破坏您的程序。例如,您可能决定稍后对这两个对象进行同步。根据规范,这些同步不应相互干扰,但如果 JVM 合并这两个对象,第一个对象的同步将不得不等待第二个对象的同步。

One thing that I have been unable to find out is if I create two new objects which are exactly the same would they refer to the same location in memory? Similar to how the String Pool works

答案是:

  1. 如果使用 new 关键字创建两个对象,它们将永远不会指向相同的内存位置。
  2. 这也适用于 String 对象。如果您使用 new 创建两个 String 对象, 对这些对象的两个引用将指向两个不同的 内存位置。
  3. String 文字是一种特殊情况。 String 文字存储在 String 文字池中。因此,对 String 文字的两个 String 引用将始终指向相同的内存位置。
  4. Java 中还有其他特殊情况,例如 Integer class。例如 Integer a = 100; Integer b = 100; System.out.println(a==b); 打印为真,因为 JVM 缓存了 -128 和 127 之间的 Integer 值。 (所有 JVM 实现都缓存了 -128 和 127 之间的值。缓存超出此范围的值取决于各个 JVM 实现)