Java 中变量的内存地址

请看下面的图片。 当我们使用 new关键字在 java 中创建一个对象时,我们从操作系统中获得一个内存地址。

当我们编写 out.println(objName)时,我们可以看到一个“特殊”字符串作为输出。我的问题是:

  1. 这个输出是什么?
  2. 如果是操作系统给我们的内存地址:

    A)如何将这个字符串转换为二进制?

    B)如何得到一个整数变量的地址?

alt text

203433 次浏览

这是类名和 IdentityHashCode (),两者之间用“@”字符分隔。标识哈希代码所表示的是特定于实现的。它通常是对象的初始内存地址,但是随着时间的推移,VM 可以将对象移动到内存中。所以(短暂地)你不能指望它是任何东西。

在 Java 中获取变量的内存地址是没有意义的,因为 JVM 可以自由地实现对象并根据需要移动它们(在垃圾收集期间,对象可能会移动等等)

ToBinaryString () 将给出二进制形式的整数。

这是 Object 的“ toString ()”实现的输出。

您得到的是 Object 类的 toString ()方法的结果,或者更准确地说,是 uzay95指出的 IdentityHashCode ()的结果。

“当我们使用新关键字在 java 中创建一个对象时,我们将从操作系统获得一个内存地址。”

重要的是要认识到,在 Java 中所做的一切都是由 Java 虚拟机处理的。是 JVM 提供了这些信息。在主机操作系统的 RAM 中实际发生的情况完全取决于 JRE 的实现。

这是 < strong > 不是内存地址 这是 < strong > classname@hashcode
这是 < a href = “ https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html # toString ()”rel = “ nofollow noReferrer”> Object.toString()的默认实现

public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

哪里

Class name = 完全限定名或绝对名(即包名后跟类名) hashcode = 十六进制格式(System.IdentityHashCode (obj)或 objec.hashCode ()将提供十进制格式的 hashcode)。

提示:
造成混淆的根本原因是 Object.hashCode()的默认实现将对象的内部地址用于整数

这通常是通过转换内部 将对象的地址转换为整数,但是这个实现 技术是不需要的 JavaTM 编程语言。

当然,有些类可以覆盖 toString()hashCode()的两个默认实现

如果需要对覆盖它的对象的默认实现值 hashcode(),
您可以使用以下方法 < a href = “ https://docs.oracle.com/javase/7/docs/api/java/lang/System.html # IdentityHashCode (java.lang.Object)”rel = “ nofollow noReferrer”> System.identityHashCode(Object x)

使用 sun.misc.Unsafe是可能的: 从@Peter Lawrey-> 有没有办法弄到参考地址?看到这个伟大的答案

使用 printAddress ()的代码:

    public static void printAddresses(String label, Object... objects) {
System.out.print(label + ": 0x");
long last = 0;
int offset = unsafe.arrayBaseOffset(objects.getClass());
int scale = unsafe.arrayIndexScale(objects.getClass());
switch (scale) {
case 4:
long factor = is64bit ? 8 : 1;
final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor;
System.out.print(Long.toHexString(i1));
last = i1;
for (int i = 1; i < objects.length; i++) {
final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor;
if (i2 > last)
System.out.print(", +" + Long.toHexString(i2 - last));
else
System.out.print(", -" + Long.toHexString( last - i2));
last = i2;
}
break;
case 8:
throw new AssertionError("Not supported");
}
System.out.println();
}

我设计了这个测试:

    //hashcode
System.out.println("Hashcode :       "+myObject.hashCode());
System.out.println("Hashcode :       "+System.identityHashCode(myObject));
System.out.println("Hashcode (HEX) : "+Integer.toHexString(myObject.hashCode()));


//toString
System.out.println("toString :       "+String.valueOf(myObject));


printAddresses("Address", myObject);

以下是输出结果:

Hashcode :       125665513
Hashcode :       125665513
Hashcode (HEX) : 77d80e9
toString :       java.lang.Object@77d80e9
Address: 0x7aae62270

结论:

  • Hashcode! = 地址
  • ToString = class@HEX (hashcode)

在 Java 中,当你从类 Person p = new Person();中创建一个对象时,p实际上是一个指向 Person类型的内存位置的地址。

当使用语句网打印 p时,您将看到一个地址。new关键字构成一个新的内存位置,包含 class Person中包含的所有实例变量和方法,p是指向该内存位置的引用变量。

就像 Sunil 说的,这不是 内存地址这只是 散列码

要获得相同的@内容,你可以:

如果在该类中没有重写 hashCode:

"@" + Integer.toHexString(obj.hashCode())

如果重写了 hashCode,则使用以下命令获取原始值:

"@" + Integer.toHexString(System.identityHashCode(obj))

这常常与内存地址混淆,因为如果不重写 hashCode () ,内存地址就会用来计算散列。

根据 Javadoc,Print 对象引用,它将返回对象的字符串表示形式,因为它将在内部从 Object 类调用 toString ()方法。 在此输入图像描述