Советы и лайфхаки

Java методы класса object – Java | Класс Object

Java Урок 42: Класс Object, методы класса object

В Java определен один специальный класс — Object. Все остальные классы
являются подклассами этого класса. То есть Object — суперкласс всех остальных классов.
Скачать исходники для статьи можно ниже

Это означает, что ссылочная переменная класса Object может ссылаться
на объект любого другого класса. Кроме того, поскольку массивы реализованы в виде классов, переменная класса Object может ссылаться также на любой массив.

Класс Object определяет некоторые методы, которые доступны в любом объекте:

1.Object clone() – Создает новый объект, не отличающийся от клонируемого

2.boolean equals(Object object) – Определяет, равен ли один объект другому

3.void finalize() – Вызывается перед удалением неиспользуемого объекта

4.Class> getClass() – Получает класс объекта во время выполнения

5.int hashCode() – Возвращает хеш-код, связанный с вызывающим объектом

6.void notify() – Возобновляет выполнение потока

7.void notifyAll() – Возобновляет выполнение всех потоков

8.String toString() – Возвращает строку, которая описывает объект

9.void wait() – Ожидает другого потока выполнения

10.void wait(long миллисек) – Ожидает другого потока выполнения

11.void wait(long миллисек,int наносек) – Ожидает другого потока выполнения

Методы getClass(), notify(), notifyAll() и wait() объявлены как final.
Остальные методы можно переопределять.

Обратите внимание на два метода: equals() и toString().
Метод equals() сравнивает два объекта. Если объекты равны, он возвращает значение true, если нет — false. Точное определение равенства зависит от типа сравниваемых объектов.

Метод toString() возвращает строку, которая содержит описание объекта,
по отношению к которому он вызван. Кроме того, этот метод автоматически вызывается при выводе объекта с помощью метода println().
Многие классы переопределяют этот метод. Это позволяет им приспосабливать описание специально для создаваемых ими объектных типов.

mnogoblog.ru

Ответы на вопросы для собеседования по Java SE (Часть 1)

Добрый, предобрый день.
В сети распространены различные варианты вопросов на собеседование по Java SE6. Но ответов на эти вопросы нет. Подумав, я решил, что это очень интересная тема для поста и дальнейшего обсуждения. И поэтому начинается цикл статей, посвященный ответам на вопросы по Java Core. За основу я взял 50 вопросов для интервьюирования.
Итак первые 5 вопросов с моими вариантами ответов:

1. Что такое класс Object? Какие в нем есть методы?
Object это базовый класс для всех остальных объектов в Java. Каждый класс наследуется от Object. Соответственно все классы наследуют методы класса Object.
Методы класса Object:

  • public final native Class getClass()
  • public native int hashCode()
  • public boolean equals(Object obj)
  • protected native Object clone() throws CloneNotSupportedException
  • public String toString()
  • public final native void notify()
  • public final native void notifyAll()
  • public final native void wait(long timeout) throws InterruptedException
  • public final void wait(long timeout, int nanos) throws InterruptedException
  • public final void wait() throws InterruptedException
  • protected void finalize() throws Throwable
Замечание: Для полноты обзора можно сказать, что существует ещё один метод private static native void registerNatives() .

2. Что такое метод equals(). Чем он отличается от операции ==.
Метод equals() обозначает отношение эквивалентности объектов. Эквивалентным называется отношение, которое является симметричным, транзитивным и рефлексивным.
  • Рефлексивность: для любого ненулевого x, x.equals(x) вернет true;
  • Транзитивность: для любого ненулевого x, y и z, если x.equals(y) и y.eqals(z) вернет true, тогда и x.equals(z) вернет true;
  • Симметричность: для любого ненулевого x и y, x.equals(y) должно вернуть true, тогда и только тогда, когда y.equals(x) вернет true.
Также для любого ненулевого x, x.equals(null) должно вернуть false.
Отличия equals() от операции == в классе Object нет. Это видно, если взглянуть исходный код метода equals класса Object:

Однако, нужно не забывать, что, если объект ни на что не ссылается(null), то вызов метода equals этого объекта приведет к NullPointerException. Также нужно помнить, что при сравнении объектов оба они могут быть null и операция obj1 == obj2 в данном случае будет true, а вызов equals приведет к исключению NullPointerException.

Как мы видим, при помощи операции == сравниваются ссылки на объекты. Но мы можем переопределять метод equals, тем самым задавая логику сравнения двух объектов. Например, рассмотрим сравнение двух одинаковых чисел, созданных при помощи класса Integer:

Если взглянуть внутрь метода equals класса Integer, то мы увидим:

Понятно, что тут уже нет сравнения ссылок, а сравниваются int значения.

3. Если вы хотите переопределить equals(), какие условия должны удовлетворяться для переопределенного метода?
Эти условия приведены в пункте 2.

4. Если equals() переопределен, есть ли какие-либо другие методы, которые следует переопределить?
Да, есть.Нужно переопределить метод hashCode(). Равные объекты должны возвращать одинаковые хэш коды. Например у класса Integer метод hashCode() переопределен следующим образом:

public int hashCode() {
return value;
}Syhi-подсветка кодаvalue это private значение, которое хранит объект класса Integer. Собственно это и есть число.5. Для чего нужен метод hashCode()?
Для начала вспомним, что такое хэш и хэширование. Теперь вспоминаем такие известные классы, как HashMap, HashSet, Hashtable, в основе которых лежит вычисление хэш-функции. Именно за счет хэша мы можем вставлять и получать данные за O(1), то есть за время пропорциональное вычислению хэш-функции.

Например, рассмотрим вставку элементов в HashMap:

public V put(K key, V value) {
...
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
...
addEntry(hash, key, value, i);
...
}Syhi-подсветка кодаКак мы видим, i-е место вставки объекта вычисляется при помощи хэша. А для вычисления нам нужна хорошая хэш функция, чтобы давала равномерное распределение и поменьше коллизий.
То есть ответ на вопрос заключается в том, что существуют коллекции(HashMap, HashSet), которые используют хэш код, как основу при работе с объектами. А если хэш для равных объектов будет разным, то в HashMap будут два равных значения, что является ошибкой. Поэтому необходимо соответствующим образом переопределить метод hashCode().

Пока, что всё. Впереди нас ждет много интересных вопросов!
До встречи.

Продолжение:
Ответы на вопросы для собеседования по Java SE (Часть 2)

dr-magic.blogspot.com

Перегрузка методов equals() и hashCode() в Java

Переопределение методов equals() и hashCode() в Java

Equals и hashCode являются фундаментальными методами объявленные в классе Object и содержатся в стандартных библиотеках Java. Метод еquals() используется для сравнения объектов, а hashCode - для генерации целочисленного кода объекта. Эти методы широко используются в стандартных библиотеках Java при вставке и извлечению объектов в HashMap. Метод equal также используется для обеспечения хранения только уникальных объектов в HashSet и других Set реализациях, а также в любых других случаях, когда нужно сравнивать объекты. Реализация по умолчанию метода equals() в классе java.lang.Object сравнивает ссылки на адреса в памяти, которые хранят переменные, и возвращает true только в том случае, если адреса совпадают, другими словами переменные ссылаются на один и тот же объект. Java рекомендует переопределять методы
equals()
и hashCode(), если предполагается, что сравнение должно осуществляться в соответсвии с естественной логикой или бизнес-логикой. Многие классы в стандартных библиотеках Java переопределяет их, например в классе String переопределяется equals таким образом, что возвращается true, если содержимое двух сравниваемых объектов одинаковое. В классе-обертке Integer метод equal переопределяется для выполнения численного сравнения, и так далее. Так как HashMap и HashTable в Java полагаются на методы equals() и hashCode() для сравнения своих key и values, то Java предлагает следующие правила для переопределения этих методов:
  1. Рефлексивность: Объект должен равняться себе самому.

  2. Симметричность: если a.equals(b) возвращает true, то b.equals(a) должен тоже вернуть true.

  3. Транзитивность: если a.equals(b) возвращает true
    и b.equals(c) тоже возвращает true, то c.equals(a) тоже должен возвращать true.

  4. Согласованность: повторный вызов метода equals() должен возвращать одно и тоже значение до тех пор, пока какое-либо значение свойств объекта не будет изменено. То есть, если два объекта равны в Java, то они будут равны пока их свойства остаются неизменными.

  5. Сравнение null: объект должны быть проверен на null. Если объект равен null, то метод должен вернуть false, а не NullPointerException. Например, a.equals(null) должен вернуть false.

Соглашение между equals и hashCode в Java.

  1. Если объекты равны по результатам выполнения метода equals, тогда их hashcode должны быть одинаковыми.

  2. Если объекты не равны по результатам выполнения метода equals, тогда их hashcode могут быть как одинаковыми, так и разными. Однако для повышения производительности, лучше, чтобы разные объекты возвращали разные коды.

Как переопределять метод equals в Java

  1. @Override
    public boolean equals(Object obj) {
    if (obj == this) {
     return true;
             }
  2. Проверьте объект на null, а также проверьте, чтобы объекты были одного типа. Не делайте проверку с помощью instanceof так как такая проверка будет возвращать true для подклассов и будет работать правильно только в случае если ваш класс объявлен как immutable. Вместо этого можно использовать getClass();

    if (obj == null || obj.getClass() != this.getClass()) {
                return false;
    }
  3. Объявите переменную типа, который вы сравниваете, и приведите obj к этому типу. Потом сравнивайте каждый атрибут типа начиная с численных атрибутов (если имеются) потому что численные атрибуты проверяются быстрей. Сравнивайте атрибуты с помощью операторов И и ИЛИ (так называемые short-circuit logical operators) для объединения проверок с другими атрибутами.

    Person guest = (Person) obj;
            return id == guest.id && (firstName == guest.firstName ||
                (firstName != null && firstName.equals(guest.getFirstName())))
                    && (lastName == guest.lastName || (lastName != null &&                      lastName .equals(guest.getLastName())));
    }
Полный пример переопределения метода equals в Java

public class Person {
    private int id;
    private String firstName;
    private String lastName;

    public int getId() { return id; }
    public void setId(int id) { this.id = id;}

    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    @Override
    public boolean equals(Object obj) {
    if (obj == this) {
        return true;
    }
    if (obj == null || obj.getClass() != this.getClass()) {
        return false;
    }

    Person guest = (Person) obj;
    return id == guest.id
        && (firstName == guest.firstName
            || (firstName != null &&firstName.equals(guest.getFirstName())))        && (lastName == guest.lastName
            || (lastName != null && lastName .equals(guest.getLastName())
            ));
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());             result = prime * result + id; result = prime * result +
        ((lastName == null) ? 0 : lastName.hashCode()); return result;
    }
 }

Распространенные ошибки при переопределении equals в Java

  1. Вместо того, чтобы переопределять метод equals (Override) программист перегружает его (Overload)Синтаксис метода equals() в классе Object определен как public boolean equals(Object obj), но многие программисты ненароком перегружают метод: public boolean equals(Person obj) - вместо Object в качестве аргумента используют имя своего класса (напр. Person). Эту ошибку сложно обнаружить из-за static binding. Таким образом, если вы вызовите этот метод для объекта своего класса, то метод не просто скомпелируется, а даже сделает это корректно. Однако, если вы положите ваш объект в коллекцию, например ArrayList и вызовите метод contains(), работа которого основана на методе equals(), то метод contains не сможет обнаружить ваш объект.

  2. При переопределении метода equals() не проверять на null переменные, что в конечном итоге заканчивается NullPointerException при вызове equals(). Ниже представлен корректный код.

    firstname == guest.firstname || (firstname != null &&
         firstname.equals(guest.firstname));

  3. Третья распространенная ошибка это не переопределять метод hashCode(), а только equals(). Вы обязаны переопределять оба метода equals() и hashCode() в Java. Метод hashCode используется в hash -коллекциях(например HashSet), и чем меньше будет коллизий (одинаковый код при разных объектах) тем эффективнее эти коллекции будут работать с объектами вашего класса.

  4. Последняя распространенная ошибка программистов в том, что при переопределении метода equals() не сохраняется соответствие между методами equals() и compareTo(), что является неформальным требованием для избежания хранения дубликатов в Set (SortedSet, TreeSet).

Подсказки как писать в Java метод equals

  1. Большинство IDE такие как NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов equals() и hashCode(). В Eclipse нажмите правую кнопку -> source -> generate equals() и hashCode().

  2. Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на равенство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.

  3. При переопределении hashCode() в Java удостоверьтесь в использовании всех полей, что были использованы в методе equals().

  4. String и классы-оболочки такие как Integer, Float и Double переопределяют метод equals(), но StringBuffer не переопределяет.

  5. При любой возможности делайте поля immutable используя final переменные в Java.

  6. При сравнении String объектов используйте equals() вместо оператора ==.

  7. Два объекта которые логически равны, но загружены из разных ClassLoader не могут быть равными. Помните, что проверка с помощью getClass() вернет false если класс-загрузчик разный.

  8. Используйте @Override аннотацию также для метода hashCode, так как это предупреждает неуловимые ошибки, например возвращаемое значение метода int, однако некоторые программисты возвращают long.

P.S. Уважаемые коллеги! Мне оказалась полезной эта статья при решении задач 21 го уровня! Желаю удачи при разборе данной темы, пользуйтесь переводом! Я надеюсь, что вы мне поможете поднять мой рейтинг, так как сейчас я даже не могу оставлять комментарий на этом форуме. Всем огромное спасибо! Оригинал статьи Я некоторые моменты опустил в связи с нехваткой свободного времени, однако перевел все, что необходимо знать для решения задач 21о уровня.

javarush.ru

Отправить ответ

avatar
  Подписаться  
Уведомление о