Как вы получаете «ссылку на объект» объекта в Java, когда toString () и hashCode () были переопределены? - PullRequest
95 голосов
/ 24 февраля 2009

Я хотел бы напечатать «ссылку на объект» объекта в Java для целей отладки. То есть чтобы убедиться, что объект один и тот же (или другой) в зависимости от ситуации.

Проблема в том, что данный класс наследует от другого класса, который переопределяет как toString (), так и hashCode (), что обычно дает мне идентификатор.

Пример ситуации: Запуск многопоточного приложения, где я (во время разработки) хочу проверить, используют ли все потоки один и тот же экземпляр объекта ресурса.

Ответы [ 6 ]

97 голосов
/ 24 февраля 2009

Что именно вы планируете делать с этим (то, что вы хотите сделать, имеет значение с тем, что вам нужно будет позвонить).

hashCode, как определено в JavaDocs, говорит:

Насколько это практически возможно, метод hashCode, определенный классом Object, возвращает разные целые числа для разных объектов. (Обычно это реализуется путем преобразования внутреннего адреса объекта в целое число, но этот метод реализации не требуется языком программирования Java & trade;).

Так что, если вы используете hashCode(), чтобы узнать, является ли это уникальный объект в памяти, который не является хорошим способом сделать это.

System.identityHashCode выполняет следующие действия:

Возвращает тот же хеш-код для данного объекта, который будет возвращен методом hashCode () по умолчанию, независимо от того, переопределяет ли класс данного объекта hashCode (). Хеш-код для нулевой ссылки равен нулю.

Что для того, что вы делаете, звучит как то, что вы хотите ... но то, что вы хотите сделать, может быть небезопасным в зависимости от того, как реализована библиотека.

47 голосов
/ 24 февраля 2009

Вот как я это решил:

Integer.toHexString(System.identityHashCode(object));
8 голосов
/ 25 февраля 2009

Double equals == всегда проверяет на основе идентичности объекта, независимо от реализации объектов hashCode или equals. Конечно, убедитесь, что ссылки на объекты, которые вы сравниваете, равны volatile (в 1.5+ JVM).

Если вам действительно нужен исходный результат Object toString (хотя это не лучшее решение для вашего примера использования), библиотека Commons Lang имеет метод ObjectUtils.identityToString (Object) , который будет то, что ты хочешь. Из JavaDoc:

public static java.lang.String identityToString(java.lang.Object object)

Получает строку toString, которая будет производится объектом, если класс не переопределить саму строку. нулевая воля вернуть ноль.

 ObjectUtils.identityToString(null)         = null
 ObjectUtils.identityToString("")           = "java.lang.String@1e23"
 ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
4 голосов
/ 24 февраля 2009

Вы не можете безопасно делать то, что хотите, так как hashCode () по умолчанию может не возвращать адрес, и, как уже упоминалось, возможно несколько объектов с одним hashCode. Единственный способ выполнить то, что вы хотите, - это переопределить метод hashCode () для рассматриваемых объектов и гарантировать, что все они предоставляют уникальные значения. Возможно ли это в вашей ситуации - это другой вопрос.

Для справки: я столкнулся с несколькими объектами с одинаковым хэш-кодом по умолчанию на виртуальной машине IBM, работающей на сервере WAS. У нас был дефект, из-за которого объекты, помещаемые в удаленный кеш, перезаписывались. В тот момент это открыло мне глаза, так как я предположил, что хеш-код по умолчанию также является адресом памяти объектов.

2 голосов
/ 24 февраля 2009

Добавьте уникальный идентификатор для всех ваших экземпляров, т.е.

public interface Idable {
  int id();
}

public class IdGenerator {
  private static int id = 0;
  public static synchronized int generate() { return id++; }
}

public abstract class AbstractSomething implements Idable {
  private int id;
  public AbstractSomething () {
    this.id = IdGenerator.generate();
  }
  public int id() { return id; }
}

Расширение от AbstractSomething и запрос этого свойства. Будет в безопасности внутри одного виртуального компьютера (при условии, что в игре нет игр с классными загрузчиками для обхода статики).

0 голосов
/ 21 мая 2015

мы можем просто скопировать код из tostring класса объекта, чтобы получить ссылка на строку

class Test
{
  public static void main(String args[])
  {
    String a="nikhil";     // it stores in String constant pool
    String s=new String("nikhil");    //with new stores in heap
    System.out.println(Integer.toHexString(System.identityHashCode(a)));
    System.out.println(Integer.toHexString(System.identityHashCode(s)));
  }
}
...