воскресенье, 18 января 2009 г.

Ответы на вопросы для собеседования по 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:

public boolean equals(Object obj) {
return (this == obj);
}Syhi-подсветка кода
Однако, нужно не забывать, что, если объект ни на что не ссылается(null), то вызов метода equals этого объекта приведет к NullPointerException. Также нужно помнить, что при сравнении объектов оба они могут быть null и операция obj1 == obj2 в данном случае будет true, а вызов equals приведет к исключению NullPointerException.
Как мы видим, при помощи операции == сравниваются ссылки на объекты. Но мы можем переопределять метод equals, тем самым задавая логику сравнения двух объектов. Например, рассмотрим сравнение двух одинаковых чисел, созданных при помощи класса Integer:

Integer a = new Integer(6);
Integer b = new Integer(6);
System.out.println(a == b); // false т.к. это разные объекты с разными ссылками
System.out.println(a.equals(b)); // true, здесь уже задействована логика сравненияSyhi-подсветка кода
Если взглянуть внутрь метода equals класса Integer, то мы увидим:

public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}Syhi-подсветка кода
Понятно, что тут уже нет сравнения ссылок, а сравниваются 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)

5 комментариев:

  1. просто спасибо большое

    ОтветитьУдалить
  2. Спасибо!
    Очень полезный материал.

    ОтветитьУдалить
  3. Спасибо :)))
    Сижу на экзамене по Ява) Это помогло всему потоку :)

    Зёма.

    ОтветитьУдалить
  4. Отличная Статья

    ОтветитьУдалить
  5. Анонимный10 мая 2010 г., 18:58

    Самое главное не останавливатся и описать все 50 вопросов - это даже будет похоже на небольшой нестандартный справочник по Java.
    Спасибо

    ОтветитьУдалить