new
关键字创建一个对象时,我们从操作系统获取一个内存地址。当我们写
out.println(objName)
时,我们可以看到一个“特殊”的字符串作为输出。我的问题是:
- 这个输出是什么?
如果它是操作系统给我们的内存地址:
a)我如何将此字符串转换为二进制?
b)我如何获取一个整数变量的地址?
new
关键字创建一个对象时,我们从操作系统获取一个内存地址。out.println(objName)
时,我们可以看到一个“特殊”的字符串作为输出。我的问题是:
如果它是操作系统给我们的内存地址:
a)我如何将此字符串转换为二进制?
b)我如何获取一个整数变量的地址?
这里的类名和System.identityHashCode()由'@'字符分隔。身份哈希码表示的内容是特定于实现的。它通常是对象的初始内存地址,但是对象可能会被虚拟机在内存中移动。因此(简要地说),您不能依赖于它代表任何东西。
在Java中获取变量的内存地址是无意义的,因为JVM可以自由地实现对象并根据需要移动它们(在垃圾收集期间,您的对象可能会移动等等)
Integer.toBinaryString()将以二进制形式返回一个整数。
identityHashcode
对于这些目的并非毫无意义,只是不是百分之百可靠的。 :) - Sled可以使用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()方法,它将打印完全不同的内容。
这不是内存地址,而是类名@哈希码
这是Object.toString()
的默认实现。
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
where
类名
= 全限定名或绝对名(即包名后跟类名)
哈希码
= 十六进制格式(System.identityHashCode(obj) 或 obj.hashCode() 将以十进制格式给出哈希码)。
提示:
混淆的根本原因是 Object.hashCode()
的默认实现将对象的内部地址转换为整数
这通常通过将对象的内部地址转换为整数来实现,但这种实现技术不是 Java™ 编程语言所必需的。
当然,一些类可以覆盖默认实现,无论是 toString()
还是 hashCode()
如果您需要覆盖其 hashcode()
方法的对象的默认实现值,
您可以使用以下方法:System.identityHashCode(Object x)
正如Sunil所说,这不是内存地址,这只是哈希码
要获取相同的@内容,你可以:
如果该类中没有覆盖hashCode方法:
"@" + Integer.toHexString(obj.hashCode())
"@" + Integer.toHexString(System.identityHashCode(obj))
这经常会与内存地址混淆,因为如果您不覆盖hashCode(),则使用内存地址来计算哈希值。
这是关于Java中哈希码(HashCode)的有用信息:
http://eclipsesource.com/blogs/2012/09/04/the-3-things-you-should-know-about-hashcode/
Person p = new Person();
,p
实际上是指向类型为Person
的内存位置的地址。p
时,你会看到一个地址。关键字new
会创建一个新的内存位置,其中包含class Person
中包括的所有实例变量和方法,而p
是指向该内存位置的引用变量。