4ca*_*tle 9 java memory tostring
该toString方法的Object独特之处在于它似乎是Java中唯一可以查看内存地址的地方.怎么Object做?
我想知道,以便我可以在我自己的课程中模仿它的实现.我无法使用,super.toString()因为我正在扩展一个toString已经覆盖的类.
更新:我的问题的前提是要求内存地址,但答案表明这个前提是不正确的,所以我实际上问的是:如何Object.toString()返回它的作用,我怎样才能模仿它?
Ell*_*sch 13
它不是内存地址,而是内存地址hashCode().另见Object.toString()(部分)
toString类的方法Object返回一个字符串,该字符串由对象为实例的类的名称,at符号字符@和对象的哈希码的无符号十六进制表示组成.换句话说,此方法返回一个等于值的字符串:Run Code Online (Sandbox Code Playgroud)getClass().getName() + '@' + Integer.toHexString(hashCode())
并Object.hashCode()说(这通常是通过将对象的内部地址转换为整数来实现的,但Java™编程语言不需要这种实现技术.)因此它不需要是内存地址,如果使用它只是可见的到内部(本机)的实现Object.
Pet*_*rey 10
Object的toString方法是唯一的,因为它似乎是Java中唯一可以查看内存地址的地方.Object如何做到这一点?
它没有获取地址,在HotSpot JVM中,它获取存储在对象标头中的随机生成的31位哈希码.这必须存储因为;
请在家里尝试,不适合工作!!
您可以使用获取/设置hashCode() Unsafe
static final Unsafe UNSAFE;
static {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
}
public static void setIdentityHashCode(Object o, int code) {
UNSAFE.putInt(o, 1l, code & 0x7FFF_FFF);
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Double d = 1.0;
Double d2 = 1.0;
setIdentityHashCode(d, 1);
setIdentityHashCode(d2, 1);
System.out.println("d: "+d+" System.identityHashCode(d): "+System.identityHashCode(d));
System.out.println("d2: "+d2+" System.identityHashCode(d2): "+System.identityHashCode(d2));
System.out.println("d == d2: " + (d == d2));
}
Run Code Online (Sandbox Code Playgroud)
版画
d: 1.0 System.identityHashCode(d): 1
d2: 1.0 System.identityHashCode(d2): 1
d == d2: false
Run Code Online (Sandbox Code Playgroud)
如果您已了解内存的翻译方式,则可以从参考值中获取地址.在最简单的情况下,(您有64位引用),引用是未转换的,地址是存储在引用中的值.
如果你在64位JVM上运行它 -XX:-UseCompressedOops
// This only works if a GC doesn't move the object while attempting to access it.
static final Unsafe UNSAFE;
static {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
}
// run with: -ea -XX:-UseCompressedOops
public static void main(String[] args) {
Object i = 0x12345678;
System.out.printf("indentityHashCode = %08x%n", System.identityHashCode(i));
Object[] obj = { i };
assert Unsafe.ARRAY_OBJECT_INDEX_SCALE == 8; // 8 bytes per reference.
long address = UNSAFE.getLong(obj, (long) Unsafe.ARRAY_OBJECT_BASE_OFFSET);
System.out.printf("%x%n", address);
for (int j=0;j<24;j++)
System.out.printf("%02x ", UNSAFE.getByte(address + j) & 0xFF);
System.out.println();
// now some really scary sh!t
UNSAFE.putLong(i, 8L, UNSAFE.getLong(0L, 8L));
System.out.printf("`i` is now a %s and is %x%n", i.getClass(), i);
}
Run Code Online (Sandbox Code Playgroud)
版画
indentityHashCode = 5a07e868
7fbf41cb8560
01 68 e8 07 5a 00 00 00 48 33 3f b9 b9 7f 00 00 78 56 34 12 00 00 00 00
^^hashCode^ ^class address ^ ^int value^
`i` is now a class java.lang.Long and is 12345678
Run Code Online (Sandbox Code Playgroud)
它没有.它得到的是哈希码,而不是内存地址,哈希码与内存地址没有必要的连接.(可能在某些实现中.)
在基本实现中System.identityHashCode,虽然它仍然与内存地址没有关系.