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...

пятница, 23 апреля 2010 г.

javax.faces.STATE_SAVING_METHOD

Вводная

javax.faces.STATE_SAVING_METHOD определяет где будет храниться состояние представления между запросами. Собственно вариантов не много: либо на стороне сервера (server), либо на стороне клиента (client).

По умолчанию используется значение server, при этом состояние сохраняется в сессии сервлета. При значении client, состояние будет сохраняться прямо в HTML код страницы. С точки зрения реализации, состояние будет сохраняться в скрытую переменную com.sun.faces.VIEW в кодировке Base64. Сохранение происходит с помощью сериализации и сериализуемый объект будет экземпляром класса com.sun.faces.util.TreeStructure.

client vs server

Сохранение состояния на стороне клиента позволяет избавиться от лишних запросов к серверу, например, от таких как повторная отправка формы. Объекты в сессии сервлета обновляются при каждой пересылке напрямую, в то время как объекты на стороне клиента, должны быть де-сериализованны при каждой пересылке. При использовании clien-side метода, нет проблем с тайм-аутом сессии, что является несомненным плюсом. Масштабируемость также является одним из преимуществ метода client-side, рост числа клиентов не требует увеличения ресурсов сервера, однако, при использовании этого метода вся нагрузка ложится на сеть. При использования метода server-side, нагрузка на сервер возрастает с увеличением числа клиентов.

В некоторых случаях, метод client-side лучше не применять, к таким случаям можно отнести ситуации когда размер состояния очень большой. Например, если представление содержит какой нибудь большой отчет с большим количеством данных. Также следует помнить о том, что при использовании метода client-side, состояние будет храниться непосредственно в коде HTML, что не всегда допустимо по соображением безопасности, но в данной ситуации всегда можно применить шифрование.
Необходимым условием использования метода server-side является использование cookies на стороне клиента.
Суммируем

Для начала лучше использовать метод server-side, с ним меньше возни и проблем. Но в дальнейшем, когда число пользователей возрастет, можно подумать о переходе к использованию метода client-side, предварительно изучив все нюансы и более подробно разобравшись в теме.

На всякий случай приведу вариант объявления:


<context-param>
   <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
   <param-value>server</param-value>
</context-param>