Как получить «ссылку на объект» объекта в Java, если toString() и hashCode() переопределены?

StackOverflow https://stackoverflow.com/questions/580984

  •  06-09-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

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

System.identityHashCode делает следующее:

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

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

Другие советы

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

Integer.toHexString(System.identityHashCode(object));

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

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

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

Получает тостронг, который будет создан объектом, если бы класс не переопределяет самого ToString.NULL вернет NULL.

 ObjectUtils.identityToString(null)         = null
 ObjectUtils.identityToString("")           = "java.lang.String@1e23"
 ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"

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

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

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

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 и запросите это свойство.Будет безопасно внутри одной виртуальной машины (при условии, что в игру не играют с загрузчиками классов, чтобы обойти статику).

Мы можем просто скопировать код из ToString of Object Class, чтобы получить ссылку на строку

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)));
  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top