Как напечатать адрес объекта, если вы переопределили метод toString
Я новичок в Java. Сейчас я изучаю equals и == и переопределение equals и toString.
Я хотел бы использовать метод toString, который я переопределил, и метод по умолчанию, унаследованный от класса Object.
Я не смог использовать этот супер модификатор, чтобы достичь этого метода.
Это только для образовательных целей. То, что я хотел бы получить, станет более понятным, если вы посмотрите комментарии в моем коде.
Не могли бы вы помочь мне здесь?
Мой код:
public class EqualTest{
public static void main(String[] args){
Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
//System.out.super.println(alice1);
Employee alice2 = alice1;
//System.out.super.println(alice2);
Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);
//System.out.super.println(alice3);
System.out.println("alice1==alice2: " + (alice1==alice2));
System.out.println("alice1 == alice3: " + (alice1==alice3));
System.out.println("alice1.equals(alice3): " + alice1.equals(alice3));
}
}
class Employee{
...
public String toString(){
return getClass().getName() + "[name = " + name +
", salary=" + salary + ", hireDay=" + hireDay + "]";
}
}
5 ответов
Строго говоря, вы не можете напечатать адрес объекта в чистом Java. Число, которое выглядит как адрес объекта в строке, созданной Object.toString()
это хеш-код объекта. Это может или не может быть связано с текущим адресом объекта:
В спецификациях не указано, как рассчитывается номер хеш-кода идентификатора. Это намеренно оставлено неуказанным.
Поскольку номер является хеш-кодом, он не может измениться. Таким образом, даже если он (как правило) связан с адресом объекта, это будет адрес объекта в момент первого обращения к хеш-коду. Это может отличаться от его текущего адреса, и оно будет другим, если GC переместил объект с момента первого наблюдения хеш-кода идентификатора объекта.
На 64-битной JVM (с достаточно большим размером кучи / без использования сжатых операций) адреса не будут вписываться в идентификационный номер хеш-кода, который возвращается как
int
,
Во всяком случае, способ получить этот номер - позвонить System.identityHashCode(obj)
,
Если вам действительно нужен текущий адрес объекта, вы можете получить его с помощью JNI и нативного метода (и некоторого нарушения абстракции) или с помощью методов в Unsafe
учебный класс. Но имейте в виду, что оба эти подхода непереносимы... и что адреса объектов, которые они вам дают, могут "сломаться" при запуске GC.
Для сомневающихся, это то, что Java 10 Javadocs говорит о точке "hashcode!= Address":
"(HashCode может или не может быть реализован как некоторая функция адреса памяти объекта в некоторый момент времени.)"
Акцент добавлен. Действительно, с недавними JVM поведение по умолчанию НЕ основывает hashCode на адресе памяти вообще. Так было по крайней мере с Java 7.
Вы можете подтвердить это, включив -XX:+PrintFlagsFinal
чтобы выяснить, что hashcode
флаг по умолчанию, а затем, глядя на исходный код OpenJDK, чтобы увидеть, что это значит. (Код находится в файле "vm/runtime/synchronizer.cpp" в некоторых версиях, но YMMV.)
Если вы хотите добиться сортировки по умолчанию toString()
поведение, вы можете использовать System.identityHashCode()
метод. По умолчанию toString()
будет выглядеть так:
public String toString(Object o) {
return o.getClass().getName() + "@" +
Integer.toHexString(System.identityHashCode(o));
}
Вы можете вызвать метод super(), чтобы выполнить соответствующий метод суперкласса.
class Employee{
...
public String toString(){
String s = super.toString();
return getClass().getName() + "[name = " + name +
", salary=" + salary + ", hireDay=" + hireDay + "]" + s;
}
toString () в классе объекта выглядит следующим образом
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Вы можете создать другой метод внутри вашего класса Employee, чтобы использовать супер метод toString.
Смотрите пример:
public class Employee {
public String toString() {
return "MyToStringMethod";
}
public String superToString() {
return super.toString();
}
public static void main(String[] args) {
Employee b = new Employee();
System.out.println(b);
System.out.println(b.superToString());
}
}
или объединить оба в одном методе:
public class Employee {
public String toString() {
return super.toString() + " MyToStringMethod";
}
public static void main(String[] args) {
Employee b = new Employee();
System.out.println(b);
}
}
Вот подробный ответ о переопределении equals и хэш-кода
Какие проблемы следует учитывать при переопределении equals и hashCode в Java?
Ключевым моментом является связь между двумя методами:
Всякий раз, когда a.equals(b), тогда a.hashCode() должен быть таким же, как b.hashCode().