среда, 22 июня 2011 г.

Что такое finalize? Зачем он нужен?

Применить finalize можно для освобождения ресурсов, которые не связаны с памятью JVM. К таким ресурсам можно отнести ресурсы операционной системы, ресурсы базы данных и т.д. Если какой либо объект занимает внешние ресурсы, то конечно их необходимо освободить,  после того как объект более недостижим. А поскольку, внешние ресурсы не связаны с памятью JVM, сборщик мусора не сможет до них дотянуться и освободить. В этих случаях, для освобождения внешних ресурсов, можно применить finalize. Но если освобождение этих ресурсов критично, то использовать finalize нельзя, так как он может вообще никогда не вызваться или вызваться когда будет уже поздно.
Еще один способ применения finalize - это своего рода защита от дурака. В этом случае, он может использоваться для подстраховки пользователя класса. Например, есть некий класс, который содержит в себе следующие методы:
  • метод open для получения каких нибудь внешних ресурсов;
  • метод close для явного освобождения полученных ресурсов. 
Для страховки в методе finalize можно проверять были ли освобождены занимаемые ресурсы.
При переопределении метода finalize, необходимо вызвать реализацию суперкласса. Если этого не сделать, то finalize суперкласса никогда не будет вызван.
protected void finalize() throws Throwable {
   try { 
      // Освобождаем необходимые ресурсы
   } finally { 
      super.finalize(); 
   }

Метод equals() класса java.lang.Object

Метод equals(), показанный ниже, должен реализовывать отношение эквивалентности:

Кроме того, метод equals() явялется:
  • Рефлексивным: Для любого значения ссылки, равного xx.equals(x) возвращает true.
  • Симметричным: Для любых значений ссылок, равных x и yx.equals(y) возвращает true только еслиy.equals(x) возвращает true.
  • Переходным: Для любых значений ссылок, равных xy и z, если x.equals(y) возвращает true и y.equals(z)возвращает true, тогда x.equals(z) должен возвращать true.
  • Последовательным: Для любых значений ссылок, равных x и y, многочисленные вызовы x.equals(y)последовательно возвращают true или false, притом, что никакая информация, используемая в равных сравнениях, не изменяется.
public boolean equals(Object obj) {
    return (obj instanceof Integer 
            && intValue() == ((Integer) obj).intValue());
  }

Метод hashCode

Метод hashCode() класса java.lang.Object возвращает значение хеш-кода для объекта. Значение хеш-кода объекта даёт целое число, которое может быть использовано некоторыми классами-коллекциями, такими как HashSet иHashtable для отображения своих объектов в области памяти. Процесс хеширования обеспечивает эффективное хранение и поиск объектов в коллекции
Пример своей реализации

public class Employee{
    int        employeeId;
    String     name;
    Department dept;
 
    // other methods would be in here 
 
    @Override
    public int hashCode() {
        int hash = 1;
        hash = hash * 17 + employeeId;
        hash = hash * 31 + name.hashCode();
        hash = hash * 13 + (dept == null ? 0 : dept.hashCode());
        return hash;
    }
}

Object. Какие его методы Вы можете назвать?

Класс Object является базовым для всех остальных классов. Он определяет методы, которые поддерживаются любым классом в Java.
Class getClass() - Возвращает класс во время выполнения
Этот метод возвращает объект класса Class, который описывает класс, от которого был порожден этот объект. Класс Class будет рассмотрен ниже. У него есть метод getName(), возвращающий имя класса:

String s = "abc";
Class cl=s.getClass();
print(cl.getName()); 
   
Результатом будет строка:
java.lang.String 
boolean  equals()- служит для сравнения объектов по значению, а не по ссылке
Поскольку сам Object не имеет полей, а значит, и состояния, в этом классе метод equals возвращает результат сравнения по ссылке
Point p1=new Point(2,3);
Point p2=new Point(2,3);
print(p1.equals(p2));
   
Результатом будет true.
int hashCode() - Возвращает hash код для объекта
 Цель hashCode() – представить любой объект целым числом
Хеш-код – это целое число, которое сопоставляется с данным объектом. Оно позволяет организовать хранение набора объектов с возможностью быстрой выборки
String toString() - Возвращает строковое представление объекта
Этот метод позволяет получить текстовое описание любого объекта. Создавая новый класс, данный метод можно переопределить и возвращать более подробное описание. Для класса Object и его наследников, не переопределивших toString(), метод возвращает следующее выражение:
getClass().getName()+"@"+hashCode()
protected Object clone() - Создает и возвращает копию этого объекта
При выполнении метода clone() сначала проверяется, можно ли клонировать исходный объект. Если разработчик хочет сделать объекты своего класса доступными для клонирования через Object.clone(), то он должен реализовать в своем классе интерфейс Cloneable. В этом интерфейсе нет ни одного элемента, он служит лишь признаком для виртуальной машины, что объекты могут быть клонированы. Если проверка не выполняется успешно, метод порождает ошибку CloneNotSupportedException.
Если интерфейс Cloneable реализован, то порождается новый объект от того же класса, от которого был создан исходный объект. При этом копирование выполняется на уровне виртуальной машины, никакие конструкторы не вызываются. Затем значения всех полей, объявленных, унаследованных либо объявленных в родительских классах, копируются. Полученный объект возвращается в качестве клона.
Почему метод clone объявлен как protected?
"потому что этот метод не реализован в Object и должен быть переопределён (возможно с расширением видимости)
Потому что объекты не поддерживают клонирование просто так. А зачем выставлять на вид метод, который не работает? Если ты сделаешь так, чтоб он работал, то тебе нужно его определить как public. 
Пример клонирования
public class Test implements Cloneable {
  Point p;
  int height;

  public Test(int x, int y, int z) {
    p=new Point(x, y);
    height=z;
  }

  public static void main(String s[]) {
    Test t1=new Test(1, 2, 3), t2=null;
    try {
      t2=(Test) t1.clone();
    } catch (CloneNotSupportedException e) {}
    t1.p.x=-1;
    t1.height=-1;
    System.out.println("t2.p.x=" + t2.p.x + ",
      t2.height=" + t2.height);
  }
}
protected void finalize() - Вызывается сборщиком мусора когда нет больше ссылок на объект
Данный метод вызывается при уничтожении объекта автоматическим сборщиком мусора (garbage collector). В классе Object он ничего не делает, однако в классе-наследнике позволяет описать все действия, необходимые для корректного удаления объекта, такие как закрытие соединений с БД, сетевых соединений, снятие блокировок на файлы и т.д. В обычном режиме напрямую этот метод вызывать не нужно, он отработает автоматически. Если необходимо, можно обратиться к нему явным образом.
В методе finalize() нужно описывать только дополнительные действия, связанные с логикой работы программы. Все необходимое для удаления объекта JVM сделает сама.