请看下面的图片。 当我们使用
new
关键字在 java 中创建对象时,我们将从操作系统获取内存地址。
当我们写
out.println(objName)
时,我们可以看到一个“特殊”字符串作为输出。我的问题是:
如果是操作系统给我们的内存地址:
a) 如何将此字符串转换为二进制?
b) 如何获取一个整型变量地址?
这是类名和 System.identityHashCode() 由“@”字符分隔。身份哈希码所代表的内容是特定于实现的。它通常是对象的初始内存地址,但随着时间的推移,VM 可以在内存中移动该对象。所以(简单地说)你不能依赖它是什么。
获取变量的内存地址在 Java 中是没有意义的,因为 JVM 可以自由地实现对象并根据需要移动它们(您的对象可能/将会在垃圾收集等过程中移动)
Integer.toBinaryString() 会给你一个二进制形式的整数。
可以使用
sun.misc.Unsafe
:请参阅 @Peter Lawrey 的这个很好的答案 -> 有办法获得参考地址吗?
使用 printAddresses() 的代码:
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
结论:
这是 Object 的“toString()”实现的输出。如果您的类重写 toString(),它将打印完全不同的内容。
这不是内存地址
这是classname@hashcode
这是
Object.toString()
的默认实现
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
哪里
Class name
= 完整限定名称或绝对名称(即包名称后跟类名称)
hashcode
= 十六进制格式(System.identityHashCode(obj) 或 obj.hashCode() 将为您提供十进制格式的哈希码)。
Object.hashCode()
的默认实现将对象的内部地址转换为整数
这通常是通过转换内部 将对象的地址转换为整数,但是这个实现 技术并不需要 Java™ 编程语言。
当然,某些类可以覆盖
toString()
或 hashCode()
的默认实现
如果您需要覆盖它的对象的默认实现值
hashcode()
,System.identityHashCode(Object x)
就像 Sunil 所说,这不是 内存地址。这只是 哈希码
要获得相同的@内容,您可以:
如果 hashCode 在该类中没有被重写:
"@" + Integer.toHexString(obj.hashCode())
如果 hashCode 被覆盖,您可以通过以下方式获得原始值:
"@" + Integer.toHexString(System.identityHashCode(obj))
这经常与内存地址混淆,因为如果不重写 hashCode(),内存地址将用于计算哈希值。
您得到的是 Object 类的 toString() 方法的结果,或者更准确地说,是 uzay95 指出的 IdentityHashCode() 的结果。
“当我们使用 new 关键字在 java 中创建对象时,我们将从操作系统获取内存地址。”
重要的是要认识到您在 Java 中所做的一切都是由 Java 虚拟机处理的。提供此信息的是 JVM。主机操作系统的 RAM 中实际发生的情况完全取决于 JRE 的实现。
在Java中,当您从像
Person p = new Person();
这样的类创建对象时,p
实际上是指向Person
类型的内存位置的地址。
当使用statemenet打印
p
时,你会看到一个地址。 new
关键字创建一个新的内存位置,其中包含class Person
中包含的所有实例变量和方法,而p
是指向该内存位置的引用变量。
根据 Javadoc,打印对象引用,它将返回对象的字符串表示形式,因为在内部它将调用 Object 类中的
toString()
方法。