JavaBranch

понедельник, 26 апреля 2010 г.

Object всему голова! (серия I)

Введение

Все классы в Java наследуются от класса java.lang.Object и, следовательно, наследуют все методы этого класса. Всего в классе Object 11 методов, 6 из них имеют модификатор final и не могут быть переопределены в наследниках. Остальные 5 методов могут переопределяться в наследниках и именно о них и пойдет речь далее. А начнем мы с самого простого...

public String toString();

Для начала, стоит обратиться к документации и ознакомится с тем, что там написано.

/**
 * Возвращает строковое представление объекта. В целом,  метод toString
 * возвращает строку, которая является лаконичным отображением этого  объекта. 
 * Результат  должен быть кратким, но информативным и человеко-читабельным.
 * Рекомендуется, чтобы все подклассы переопределяли  этот метод.
 *
 * Метод toString класса Object возвращает строку, содержащую название класса,
 * экземпляром которого является объект, далее следует символ @ и беззнаковое
 * шестнадцатеричное представление хеш-кода объекта. Другими словами, этот
 * метод возвращает строку, эквивалентную результату выполнения кода:
 * 
 *         getClass().getName() + '@' + Integer.toHexString(hashCode())
 */
Что касается переопределения метода toString для классов, прямых наследников класса Object, то в большинстве случаев делать это нужно. Переопределяя метод toString Вы делаете класс гораздо более приятным в использовании и, сами того не подозревая, можете облегчить многие вещи для пользователей класса. К тому же, переопределение метода toString является хорошим тоном и считается общепринятой практикой. Но, в некоторых случаях переопределением toString все же можно пренебречь. К таким случаям можно отнести классы, экземпляры которых никогда не могут быть созданы, а следовательно, метод toString никогда не сможет быть выполнен. Например, такие классы как Collections, Math и им подобные не предназначены для создания экземпляров и переопределять в них описываемый метод нет смысла.

Для полноты картины, разберем следующий пример кода:

             System.out.println("Output: " + Runtime.getRuntime());
Класс Runtime является прямым наследником класса Object, но не переопределяет метод toString. В результате выполнения кода мы получим примерно следующий результат:

             console> Output: java.lang.Runtime@42e816
В принципе, тут все просто и понятно. Но на один момент, все же стоит обратить внимание, имеется ввиду конкатенация. Если в конкатенации участвует параметр отличный от строки (примитивы опускаются), то к данному параметру применяется преобразование вида String.valueOf(param), в следствии которого происходит приведение параметра к строковому представлению. И что самое главное, происходит это как раз с помощью метода toString.

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

При переопределении метода toString необходимо позаботиться и о документации. В документации необходимо описать формат возвращаемого значения и все его возможные варианты.

Думаю, что на этом можно закончить. В титрах суммируем все описанное выше:
Любой объект, любого класса может быть представлен в виде строки и у создателей класса есть возможность переопределить это представление. Использовать эту возможность или не использовать - решать Вам, но если решили переопределять метод toString, то будьте добры написать документацию на Вашу реализацию.
ПС: есть замечательная библиотека Apache Commons Lang, которая может помочь в реализации метода toString. Выглядит это примерно так:
public class Person {
   String name;
   int age;
   boolean smoker;

   ...

   public String toString() {
     return new ToStringBuilder(this).
       append("name", name).
       append("age", age).
       append("smoker", smoker).
       toString();
   }
 }
Для более подробной информации можно обратиться к документации.

Продолжение следует, в следующей серии о finalize...

2 комментария:

  1. подскажите, пожалуйста, где Вы взяли документацию на русском языке?

    ОтветитьУдалить
  2. Сам перевел, благо текст там не сложный.

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