156

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

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

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

    a)如何将此字符串转换为二进制?

    b) 我怎样才能得到一个整数变量地址?

替代文字

4

9 回答 9

189

那是类名和System.identityHashCode()由“@”字符分隔。身份哈希码所代表的内容是特定于实现的。它通常是对象的初始内存地址,但随着时间的推移,VM 可以在内存中移动对象。所以(简要地)你不能指望它是任何东西。

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

Integer.toBinaryString()会给你一个二进制形式的整数。

于 2009-12-25T13:14:14.427 回答
39

可以使用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

结论 :

  • 哈希码!=地址
  • toString = 类@HEX(哈希码)
于 2013-12-19T11:34:07.723 回答
13

那是 Object 的“toString()”实现的输出。如果您的类覆盖 toString(),它将打印完全不同的内容。

于 2009-12-25T13:30:38.970 回答
10

不是内存地址 这是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)

于 2013-12-18T06:08:04.933 回答
7

就像 Sunil 说的,这不是内存地址。这只是哈希码

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

如果该类中未覆盖 hashCode:

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

如果 hashCode 被覆盖,您将获得原始值:

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

这通常与内存地址混淆,因为如果您不覆盖 hashCode(),则内存地址用于计算哈希。

于 2016-08-09T13:50:32.490 回答
1

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

“当我们在 java 中使用 new 关键字创建对象时,我们会从操作系统获取内存地址。”

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

于 2009-12-25T20:57:55.620 回答
0

这对于了解 java 中的哈希码很有用:

http://eclipsesource.com/blogs/2012/09/04/the-3-things-you-should-know-about-hashcode/

于 2015-04-20T12:17:48.413 回答
0

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

于 2022-03-05T17:50:22.973 回答
-1

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

使用statemenet 打印p时,您会看到一个地址。new关键字创建一个新的内存位置,其中包含所有实例变量和方法,并且class Personp指向该内存位置的引用变量。

于 2016-01-01T05:35:50.837 回答