<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="http://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:java_master</id>
  <title>Java за рамками учебника</title>
  <subtitle>java_master</subtitle>
  <author>
    <name>java_master</name>
  </author>
  <link rel="alternate" type="text/html" href="http://java-master.livejournal.com/"/>
  <link rel="self" type="text/xml" href="http://java-master.livejournal.com/data/atom"/>
  <updated>2008-07-02T06:28:27Z</updated>
  <lj:journal userid="15965952" username="java_master" type="personal"/>
  <link rel="service.feed" type="application/x.atom+xml" href="http://java-master.livejournal.com/data/atom" title="Java за рамками учебника"/>
  <link rel="hub" href="http://pubsubhubbub.appspot.com/"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:java_master:2349</id>
    <link rel="alternate" type="text/html" href="http://java-master.livejournal.com/2349.html"/>
    <link rel="self" type="text/xml" href="http://java-master.livejournal.com/data/atom/?itemid=2349"/>
    <title>JDK: подноготная стандартной библиотеки. Часть 3. Java Core: строки</title>
    <published>2008-06-30T13:14:39Z</published>
    <updated>2008-06-30T22:58:22Z</updated>
    <category term="оптимизация"/>
    <category term="jdk"/>
    <category term="java core"/>
    <category term="задача на дом"/>
    <category term="стандартные библиотеки"/>
    <content type="html">Java задумывалась как язык, в котором на уровне синтаксиса и стандартной библиотеки обеспечивается более высокая безопасность в сравнении с обычными компиляторами вроде С и одновременно с этим более высокая производительность в сравнении с обычными интерпретаторами. &lt;br /&gt;&lt;br /&gt;Именно с такими мыслями создавался объект String. Строка в Java является немодифицируемой. &lt;a href="http://java-master.livejournal.com/1893.html"&gt;Как и для оберток&lt;/a&gt;, это сделано с целью обеспечить потоковую безопасность. Ведь если объект константен, то он &lt;a href="http://en.wikipedia.org/wiki/Thread-safety"&gt;thread-safe&lt;/a&gt;(en). Итак, вопрос с поточной безопасностью решен. А что же с производительностью?&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;div class="ljcut" text="Read more..."&gt; Часто возникает необходимость конкатенировать большое количество строк. Если делать это с помощью одних только строк, то возникает существенное падение производительности:&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" size="2" color="black"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#2b91af"&gt;String&lt;/font&gt; readStream(Reader &lt;font color="#0000ff"&gt;is&lt;/font&gt;) throws IOException {&lt;br /&gt;&amp;nbsp;&amp;nbsp;BufferedReader isr = &lt;font color="#0000ff"&gt;new&lt;/font&gt; BufferedReader(&lt;font color="#0000ff"&gt;is&lt;/font&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#2b91af"&gt;String&lt;/font&gt; result=&lt;font color="#a31515"&gt;""&lt;/font&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#2b91af"&gt;String&lt;/font&gt; buffer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;while&lt;/font&gt; ( (buffer = isr.readLine()) !=&lt;font color="#0000ff"&gt;null&lt;/font&gt;) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result+=buffer + &lt;font color="#a31515"&gt;"\n"&lt;/font&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;return&lt;/font&gt; result;&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Задача на дом №1:&lt;/span&gt;&amp;nbsp; Какие проблемы производительности у приведенного кода? Чему асимптотически равен суммарный объем всей выделенной памяти в этом методе?&lt;br /&gt;&lt;br /&gt;Специально для таких случаев в JDK предусмотрены классы StringBuffer и StringBuilder. Оба класса представляют из себя строковой буфер для множества последовательных конкатенаций. В чем отличия этих классов? (хороший вопрос на собеседование). Отличие в том, что StringBuffer является thread-safe, а StringBuilder - нет. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Совет:&lt;/span&gt; используй StringBuilder там, где это возможно и StringBuffer - там, где это необходимо. &lt;br /&gt;&lt;br /&gt;Поскольку предполагается использование StringBuffer в многопоточной среде, то данные в буфер скорее всего будут записываться в хаотичном порядке. Доказательство от противного: если порядок записи в StringBuffer четко определён, то это означает наличие дополнительной рукописной синхронизации, из чего следует, что доступ к StringBuffer синхронизирован, и в этом случае следует использовать StringBuilder.&amp;nbsp; Я вижу только один тип задач, которые следует решать средствами StringBuffer - это задачи протоколирования событий в системе. Например, логирование. Предлагаю читателям попробовать опровергнуть это утверждение или привести еще примеры использования StringBuffer.&lt;br /&gt;&lt;br /&gt;И так, если строковой буфер находится в локальном контексте потока, то используем StringBuilder, иначе - StringBuffer. &lt;br /&gt;&lt;br /&gt;Правильная реализация предыдущей задачи с использованием StringBuilder:&lt;blockquote&gt;&lt;font face="Courier New" size="2" color="black"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#2b91af"&gt;String&lt;/font&gt; readStream(Reader &lt;font color="#0000ff"&gt;is&lt;/font&gt;) throws IOException {&lt;br /&gt;&amp;nbsp;&amp;nbsp;BufferedReader isr = &lt;font color="#0000ff"&gt;new&lt;/font&gt; BufferedReader(&lt;font color="#0000ff"&gt;is&lt;/font&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#2b91af"&gt;StringBuilder&lt;/font&gt; result = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#2b91af"&gt;StringBuilder&lt;/font&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#2b91af"&gt;String&lt;/font&gt; buffer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;while&lt;/font&gt; ((buffer = isr.readLine()) != &lt;font color="#0000ff"&gt;null&lt;/font&gt;) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result.append(buffer).append(&lt;font color="#a31515"&gt;"\n"&lt;/font&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;return&lt;/font&gt; result.toString();&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;/blockquote&gt; &lt;span style="font-weight: bold;"&gt;Задача на дом №2 (сложная):&lt;/span&gt;&amp;nbsp; Чему асимптотически равен суммарный объем всей выделенной памяти в этой реализации?&lt;br /&gt;&lt;br /&gt;А вот интересные результаты &lt;a href="http://www.infoq.com/articles/java-threading-optimizations-p1"&gt;тестирования производительности этих классов&lt;/a&gt;&lt;/div&gt;&lt;a href="http://www.infoq.com/articles/java-threading-optimizations-p1"&gt;&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:java_master:1893</id>
    <link rel="alternate" type="text/html" href="http://java-master.livejournal.com/1893.html"/>
    <link rel="self" type="text/xml" href="http://java-master.livejournal.com/data/atom/?itemid=1893"/>
    <title>JDK: подноготная стандартной библиотеки. Часть 2. Java Core: обертки</title>
    <published>2008-06-29T11:15:40Z</published>
    <updated>2008-06-29T18:03:20Z</updated>
    <category term="wrappers"/>
    <category term="jdk"/>
    <category term="обертки"/>
    <category term="java core"/>
    <category term="задача на дом"/>
    <category term="стандартные библиотеки"/>
    <content type="html">&lt;a&gt;&lt;img height="240" width="286" border="0" align="right" src="http://pics.livejournal.com/java_master/pic/00003r8k/s320x240" alt="Классы обертки" /&gt;&lt;/a&gt;В java в отличие от например С   потребовалось четко разделить понятия примитивных типов и объектов. Здесь объекты всегда хранятся по ссылке, а примитивы - всегда по значению. &lt;br /&gt;&lt;br /&gt;Если мы хотим сказать, что &lt;i&gt;данное поле конкретного примитивного типа&lt;/i&gt;, то используем примитив. &lt;br /&gt;&lt;br /&gt;Если мы хотим сказать, что данное поле &lt;i&gt;какого-то примитивного типа&lt;/i&gt;, то используем базовый тип всея объектов - Object. &lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;div class="ljcut" text="Read more..."&gt;Такой тип означает ссылку на всё, что угодно. Но ссылаться на примитив мы не можем, значит, используем ссылку на "объект, похожий на примитив" - обёртку. Поэтому были созданы классы обертки Byte, Double, Float, Integer, Long, Short, Character, целью которых является предоставление унифицированного доступа к примитивным типам. &lt;br /&gt;&lt;br /&gt;Значения примитивных типов нельзя модифицировать. На первый взгляд это очень неудобно. Но если вспомнить цель типов-оболочек - объектный аналог примитивного типа - и поразмышлять, то становится понятно, почему разработчики JDK приняли такое решение:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;примитивные типы атомарны, следовательно, они &lt;a href="http://en.wikipedia.org/wiki/Thread_safe"&gt;thread-safe(en)&lt;/a&gt;. Самый экономичный способ достичь этого - сделать константный объектный аналог примитивного типа.&amp;nbsp;&lt;/li&gt;&lt;li&gt;примитивные типы передаются всегда по значению. Следовательно нет возможности через параметр вернуть значение примитивного типа или случайно его модифицировать в методе. Простой способ добиться этого - опять же константная оболочка.&amp;nbsp; &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Пример:&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" size="2" color="black"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#0000ff"&gt;void&lt;/font&gt; increment(Integer i) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;i ++ ;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;Здесь увеличенное значение i не возвращается вызвавшему методу. Имитируется передача параметра по значению.&lt;br /&gt;&lt;br /&gt; &lt;b&gt;Совет: &lt;/b&gt;используйте примитивы везде, где можете, а обертки - только там, где это необходимо.&lt;br /&gt;&lt;br /&gt;Рассмотрим для примера решение задачи увеличения элементов массива на некоторую величину для векторов и массивов. &lt;br /&gt;Используется синтаксис Java 2: &lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" size="2" color="black"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#0000ff"&gt;void&lt;/font&gt; incArray(&lt;font color="#0000ff"&gt;int&lt;/font&gt; []m, &lt;font color="#0000ff"&gt;int&lt;/font&gt; v) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;for&lt;/font&gt; (&lt;font color="#0000ff"&gt;int&lt;/font&gt; i=0; i&amp;lt;m.length; i  ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m[i]  += v;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#0000ff"&gt;void&lt;/font&gt; incList(&lt;font color="#2b91af"&gt;List&lt;/font&gt; l, &lt;font color="#0000ff"&gt;int&lt;/font&gt; v) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;for&lt;/font&gt; (&lt;font color="#0000ff"&gt;int&lt;/font&gt; i=0;i&amp;lt;l.size(); i  ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;l.&lt;font color="#0000ff"&gt;set&lt;/font&gt;(i, &lt;font color="#0000ff"&gt;new&lt;/font&gt; Integer(((Integer)l.&lt;font color="#0000ff"&gt;get&lt;/font&gt;(i)).intValue()+ v));&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;Для массивов можно воспользоваться примитивными типами. Операция увеличения ячейки массива выполняется простым оператором.&amp;nbsp; В случае со списком аналогичная операция включает в себя три вызова метода, оператор сложения, создание одного и удаление другого объекта (предыдущего значения элемента списка). Конечно, это приводит не только глаза в кучу, но и значительно снижает производительность приложения. &lt;br /&gt;&lt;br /&gt;А как же синтаксис Java 5? &lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" size="2" color="black"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#0000ff"&gt;void&lt;/font&gt; incListJava5(&lt;font color="#2b91af"&gt;List&lt;/font&gt;&amp;lt;Integer&amp;gt; l, &lt;font color="#0000ff"&gt;int&lt;/font&gt; v) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;for&lt;/font&gt; (&lt;font color="#0000ff"&gt;int&lt;/font&gt; i=0;i&amp;lt;l.size(); i  ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;l.&lt;font color="#0000ff"&gt;set&lt;/font&gt;(i, l.&lt;font color="#0000ff"&gt;get&lt;/font&gt;(i) +v);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;Казалось бы, осталось всего два вызова метода и оператор сложения. Но это всего лишь &lt;a href="http://ru.wikipedia.org/wiki/Синтаксический_сахар"&gt;syntax sugar &lt;/a&gt;- небольшое синтаксическое улучшение. Оно не должно вводить в заблуждение о количестве выполняемых кодом операций. В последнем примере остались все те же три вызова методов, сложение и создания, удаления объектов. &lt;br /&gt;&amp;nbsp;&lt;br /&gt;Красота достигается за счет нововведения java 5 - autoboxing. &lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html"&gt;Autoboxing&lt;/a&gt; автоматически преобразует примитивные типы к их аналогам оболочкам и наоборот. &lt;br /&gt;&lt;br /&gt;Будьте внимательны с autoboxing! Из-за неявных преобразований, могут возникнуть недопонимания. Следующий код не будет корректно решать задачу. В чем проблема этого кода предлагаю ответить моим читателям белым шрифтом в комментариях.&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" size="2" color="black"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#0000ff"&gt;void&lt;/font&gt; incListJava5(&lt;font color="#2b91af"&gt;List&lt;/font&gt;&amp;lt;Integer&amp;gt; l, &lt;font color="#0000ff"&gt;int&lt;/font&gt; v) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;for&lt;/font&gt; (Integer i:l) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i +=v;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;Вроде бы всё ясно. Но кому тогда нужна оболочка java.lang.Void ?? Об этом - в следующих статьях.&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:java_master:1605</id>
    <link rel="alternate" type="text/html" href="http://java-master.livejournal.com/1605.html"/>
    <link rel="self" type="text/xml" href="http://java-master.livejournal.com/data/atom/?itemid=1605"/>
    <title>JDK: подноготная стандартной библиотеки. Часть 1. Java Core: java.lang.Object</title>
    <published>2008-06-29T11:13:39Z</published>
    <updated>2008-06-30T11:41:16Z</updated>
    <category term="java.lang.object"/>
    <category term="jdk"/>
    <category term="приемы программирования"/>
    <category term="java core"/>
    <category term="стандартные библиотеки"/>
    <content type="html">JDK - как много в этом звуке для сердца джавера слилось!&lt;br /&gt;&amp;nbsp;&lt;a&gt;&lt;img height="240" border="0" align="right" width="214" alt="Классы Java" src="http://pics.livejournal.com/java_master/pic/00002271/s320x240" /&gt;&lt;/a&gt;&lt;br /&gt;Действительно ли так много? Да, 19184 класса в моей JDK 1.6.0 UPDATE 3. Большая часть из них закрыта, но и оставшихся нескольких тысяч открытых классов больше, чем достаточно.&amp;nbsp; Но ведь даже сертифицированному Java программисту нелегко на память перечислить хотя бы полсотни из них!&lt;br /&gt;&lt;br /&gt;Почему мы так мало знаем о классах JDK? Причины у всех свои, но думаю, что основным стоппером в использовании малоизвестных классов является незнание того, как именно они могут помочь более эффективно решить поставленную задачу. Обзору особенностей популярных и возможностей менее популярных классов JDK будет посвящен этот цикл статей. &lt;br /&gt;&lt;br /&gt;С чего начнем? Конечно, с java core! &lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;div class="ljcut" text="Read more..."&gt;&lt;br /&gt;java.lang.*&lt;br /&gt;&lt;br /&gt;Этот пакет представлен классами обертками, основными классами исключений, классами &lt;code&gt;Object, Class, Math, System, Runtime, Thread, ThreadLocal, String, StringBuffer, StringBuilder&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Все данные в Java делятся на объекты и примитивные типы. Примитивные типы нам неинтересны - их знает даже программист на BASIC. А все объекты являются наследниками java.lang.Object. Если не знаешь, что такое наследование, то тебе скорее всего &lt;a href="http://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5"&gt;сюда&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;java.lang.Object&lt;/code&gt; обладает тем поведением, которым должен обладать любой объект в Java. Что это за поведение?&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" color="black" size="2"&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; boolean equals(Object obj); &lt;/font&gt;&lt;/blockquote&gt; &lt;br /&gt;&lt;br /&gt;Метод выполняет проверку на эквивалентность другому объекту. Реализация по-умолчанию проверяет совпадение ссылок на объект - это работает очень быстро и обладает адекватной семантикой. Твоя реализация может:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Сравнивать уникальные идентификаторы объекта&lt;/li&gt;&lt;li&gt;Сравнивать "первичные ключи" - уникальные наборы полей&lt;/li&gt;&lt;li&gt;Выполнять полную (глубокую) проверку эквивалентности полей объекта&lt;/li&gt;&lt;/ul&gt;Дальше курсив - это возможная реплика абстрактного читателя. &lt;i&gt;&lt;br /&gt;- А зачем это вообще надо? Я вот никогда не использую этот метод. У себя в программе вообще могу написать отдельную функцию, сравнивающую объекты или определить свой метод myequals внутри объекта. Он будет так же хорош для моей задачи. &lt;/i&gt;&lt;br /&gt;- equals активно используется контейнерами стандартной библиотеки. Не определил у себя в объекте нормальный equals - лишился возможности использовать объект в контейнере. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" color="black" size="2"&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; &lt;font color="#0000ff"&gt;int&lt;/font&gt; hashCode();&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Метод создает хэш код объекта. По умолчанию хэш код генерируется из адреса объекта. Этот метод нужен только для использования внутри хэш таблиц (java.util.HashSet) . Зачем ради каких то хэш таблиц заводить целый метод для всех(!) объектов языка? Затем, что хэш таблицы и карты используются в языке повсеместно. А если ты еще не используешь их, то мы идём за тобой!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Правило: &lt;/span&gt;Если твои объекты совпадают по equals, то у них &lt;span style="font-style: italic;"&gt;обязан быть&lt;/span&gt; одинаковый hashCode. Если объекты различаются по equals, то &lt;span style="font-style: italic;"&gt;рекомендуется&lt;/span&gt; сделать для них разный hashCode. Подробнее расскажу в теме о контейнерах.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Правило:&lt;/b&gt; всегда переопределяйте equals одновременно с hashCode, если собираетесь использовать объект вместе с хэш таблицами! &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" color="black" size="2"&gt;&lt;font color="#0000ff"&gt;protected&lt;/font&gt; &lt;font color="#0000ff"&gt;void&lt;/font&gt; finalize() &lt;/font&gt;&lt;/blockquote&gt; &lt;br /&gt;&lt;br /&gt;Очень странный метод, который по стандарту &lt;span style="font-style: italic;"&gt;может вызваться&lt;/span&gt; при разрушении объекта. А может и не вызываться. Раз он такой непостоянный, то не стоит вообще на него обращать внимания.&amp;nbsp; И даже не пытайтесь закрывать в нем открытые ранее потоки/файлы/сокеты! И не стоит путать его с деструкторами объекта из С++.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Совет: &lt;/span&gt;забей на finalize&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" color="black" size="2"&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; final Class getClass();&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;Метод получает класс объекта. Логично, что его нельзя переопределить, а тем, кому всё же хочется, следует руки поотрывать. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Совет:&lt;/span&gt; если вам понадобился getClass(), то, возможно, лучше модифицировать эту часть кода с использованием полиморфизма. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" color="black" size="2"&gt;&lt;font color="#0000ff"&gt;protected&lt;/font&gt; native Object clone() throws CloneNotSupportedException;&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Метод возвращающий &lt;a href="http://en.wikipedia.org/wiki/Deep_copy#Shallow_copy"&gt;поверхностную копию(en)&lt;/a&gt; данного объекта. Используется как конструктор копирования в с++.&lt;br /&gt;По-умолчанию является наследуемым (protected) и в случае, если объект не реализует интерфейс Coneable, кидает исключение CloneNotSupportedException. Вопрос того, почему clone() является protected, да еще и кидает исключения, донимает лучшие умы тысячелетия. Моё объяснение этого феномена таково:&amp;nbsp; clone является protected по той причине, что разработчики jdk дают нам возможность использовать функционал поведения clone по-умолчанию, но при этом не хотят чтобы, опасная и неочевидная семантика поверхностного копирования была по-умолчанию доступна всем пользователям объекта. &lt;br /&gt;&lt;br /&gt;У clone есть два серьезных недостатка:&lt;br /&gt;1. clone возвращает Object. Это даёт повод возвращать объекты другого типа. Но за такие вещи нужно наказывать двухнедельными принудительными работами на языке Cobol.&lt;br /&gt;2. Если ты знаешь, что некий наследник класса Object можно клонировать, то ты не вызовишь метод clone иначе, как через reflection api. Например, в твоей нетипизированной коллекции находятся различные объекты. Некоторые из них можно клонировать, т. е. они реализуют интерфейс Cloneable. К какому общему базовому интерфейсу нужно выполнить кастомизацию типа, чтобы вызвать метод clone? По-умолчанию нет такого интерфейса. Сам Cloneable не содержит внутри себя объявления открытого метода clone. Cloneable - пустой интерфейс и по сути является всего лишь меткой. &lt;br /&gt;&lt;br /&gt;Более подробно про &lt;a href="http://en.wikipedia.org/wiki/Clone_%28Java_method%29"&gt;метод clone&lt;/a&gt;.&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Совет:&lt;/span&gt; хотите заниматься клонированием? Заведите нормальный интерфейс Clone:&lt;br /&gt;&lt;blockquote&gt;&lt;font face="Courier New" color="black" size="2"&gt;&lt;font color="#0000ff"&gt;interface&lt;/font&gt; Clone&amp;lt;T&amp;gt; extends Cloneable {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;public&lt;/font&gt; T clone() throws CloneNotSupportedException;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#0000ff"&gt;class&lt;/font&gt; Dolly implements Clone&amp;lt;Dolly&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;private&lt;/font&gt; &lt;font color="#2b91af"&gt;String&lt;/font&gt; DNA;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;public&lt;/font&gt; Dolly(&lt;font color="#2b91af"&gt;String&lt;/font&gt; s) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DNA = s;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;public&lt;/font&gt; Dolly clone() throws CloneNotSupportedException {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;return&lt;/font&gt; (Dolly) super.clone();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt; &lt;font color="#0000ff"&gt;static&lt;/font&gt; &lt;font color="#0000ff"&gt;void&lt;/font&gt; main(&lt;font color="#2b91af"&gt;String&lt;/font&gt;[] args) throws IOException, CloneNotSupportedException {&lt;br /&gt;&amp;nbsp;&amp;nbsp;Dolly dolly = &lt;font color="#0000ff"&gt;new&lt;/font&gt; Dolly(&lt;font color="#a31515"&gt;"TTAGGCGGCATTACGG"&lt;/font&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#2b91af"&gt;ArrayList&lt;/font&gt; myObjects = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#2b91af"&gt;ArrayList&lt;/font&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;myObjects.add(&lt;font color="#0000ff"&gt;new&lt;/font&gt; Integer(123));&lt;br /&gt;&amp;nbsp;&amp;nbsp;myObjects.add(dolly);&lt;br /&gt;&amp;nbsp;&amp;nbsp;Set clones = &lt;font color="#0000ff"&gt;new&lt;/font&gt; HashSet();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;for&lt;/font&gt; (Object o : myObjects) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;if&lt;/font&gt; (o instanceof Clone) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clones.add(((Clone) o).clone());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#008000"&gt;// здесь в clones находится только один объект Dolly&lt;/font&gt;&lt;br /&gt;}&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Остались методы &lt;code&gt;notify, notifyAll, wait&lt;/code&gt;, которые используются для организации многопоточности. О них я постараюсь написать в статье про потоки. &lt;br /&gt;&lt;br /&gt;Также есть метод &lt;code&gt;toString&lt;/code&gt;, не представляющий никакого интереса для любознательных кроме того, что позволяет выполнять приведение типа к &lt;code&gt;String&lt;/code&gt; автоматически:&lt;br /&gt;&lt;br /&gt; &lt;blockquote&gt;&lt;font face="Courier New" color="black" size="2"&gt;System.&lt;font color="#0000ff"&gt;out&lt;/font&gt;.println(&lt;font color="#a31515"&gt;"Dolly's value is "&lt;/font&gt;+&lt;font color="#0000ff"&gt;new&lt;/font&gt; Dolly());&lt;/font&gt;&lt;/blockquote&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Все эти методы пришли к нам из далекого прошлого становления языка Java. Не судите их слишком строго.&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:java_master:1493</id>
    <link rel="alternate" type="text/html" href="http://java-master.livejournal.com/1493.html"/>
    <link rel="self" type="text/xml" href="http://java-master.livejournal.com/data/atom/?itemid=1493"/>
    <title>Примерный список тем для статей</title>
    <published>2008-06-28T21:37:19Z</published>
    <updated>2008-07-02T06:28:27Z</updated>
    <category term="обзор"/>
    <content type="html">По вашим многочисленным просьбам выкладываю примерный список тем, которые собираюсь осветить в ближайшее время.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Паттерны/Антипаттерны. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Рефакторинг. Автоматический рефакторинг в Intellij Idea&lt;/li&gt;&lt;li&gt;Алгоритмическая оптимизация. Обзор основных алгоритмов. Динамическое программирование против тормозных задач.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Языковая оптимизация.&lt;/li&gt;&lt;li&gt;Хитрости стандартной библиотеки.&lt;/li&gt;&lt;li&gt;Библиотеки apache commons как расширения стандартной библиотеки. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Hibernate. Как его приручить?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Spring vs Struts.&amp;nbsp;&lt;/li&gt;&lt;li&gt;DWR, GWT, другие Ajax фреймворки. Сравнение, рекомендации по выбору подходящего.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Java Generics vs C++ Templates. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Новшества Java 6&lt;/li&gt;&lt;/ul&gt;В этот список могут попасть темы, предложенные вами!&lt;br /&gt;&lt;br /&gt;Темы моих читателей:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Velocity&lt;/li&gt;&lt;li&gt;Веб сервисы&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:java_master:1197</id>
    <link rel="alternate" type="text/html" href="http://java-master.livejournal.com/1197.html"/>
    <link rel="self" type="text/xml" href="http://java-master.livejournal.com/data/atom/?itemid=1197"/>
    <title>Не изобретайте колёса! 6 причин пользоваться существующими</title>
    <published>2008-06-28T14:27:58Z</published>
    <updated>2008-06-30T09:59:57Z</updated>
    <category term="задача на дом"/>
    <category term="стандартные библиотеки"/>
    <content type="html">&lt;a&gt;     &lt;img height="211" border="0" align="right" width="320" alt="Колёса для марсианских роверов" title="Колёса для марсианских роверов" src="http://pics.livejournal.com/java_master/pic/00001x04/s320x240" /&gt; &lt;/a&gt;- Ну хватит уже этих банальностей про колёса, надоело!  - скажешь ты. &lt;br /&gt;&lt;br /&gt;А вот и не хватит! В современном научном мире и мире программирования колёса изобретают только &lt;strike&gt;идиоты&lt;/strike&gt;бунтари и студенты - в качестве домашнего задания. &lt;br /&gt; &amp;nbsp; &lt;a&gt;     &lt;/a&gt;&lt;br /&gt;Java - это такой особенный язык, разработчики которого очень продуманно подошли к проблеме разработки стандартных библиотек. Так что колес здесь своих достаточно на любой вкус и цвет. &lt;strike&gt;Глотай&lt;/strike&gt; бери - не хочу! &lt;br /&gt;Вот список из 6 причин использовать существующие наработки для тех, кто еще не уверовал: &lt;b&gt;     &lt;br /&gt;     &lt;/b&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;div class="ljcut" text="Read more..."&gt;&lt;b&gt;&lt;br /&gt;     1. Свое колесо - восьмеркой.     &lt;br /&gt; &lt;/b&gt;Доказательство тривиальное. Чем больше написано кода, тем больше допущено ошибок. Значит, код вашего колеса вероятно будет содержать ошибки. С другой стороны штампованое серийно выпущенное колесо (многократно протестированные библиотеки) содержит минимум  ошибок. &lt;br /&gt; &lt;br /&gt;Возьмем классическую задачу сортировки массива. Пусть требуется отсортировать массив Person по неубыванию имени. Сортировка выполняется по имени или фамилии в зависимости от параметра.  &lt;blockquote&gt;&lt;font face="Courier New" color="black" size="2"&gt;&lt;font color="#0000ff"&gt;class&lt;/font&gt; Person {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#2b91af"&gt;String&lt;/font&gt; name;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#2b91af"&gt;String&lt;/font&gt; surname;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#2b91af"&gt;String&lt;/font&gt; getName(&lt;font color="#0000ff"&gt;int&lt;/font&gt; index) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;return&lt;/font&gt; index == 0 ? name : surname;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt; nativeSort(Person[] persons, final &lt;font color="#0000ff"&gt;int&lt;/font&gt; index) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;Arrays.sort(persons, &lt;font color="#0000ff"&gt;new&lt;/font&gt; Comparator&amp;lt;Person&amp;gt;() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;public&lt;/font&gt; &lt;font color="#0000ff"&gt;int&lt;/font&gt; compare(Person o1, Person o2) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;return&lt;/font&gt; o1.getName(index).compareTo(o2.getName(index));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt; mySort(Person[] persons, &lt;font color="#0000ff"&gt;int&lt;/font&gt; index) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;for&lt;/font&gt; (&lt;font color="#0000ff"&gt;int&lt;/font&gt; i = 0; i &amp;lt; persons.length - 1; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;for&lt;/font&gt; (&lt;font color="#0000ff"&gt;int&lt;/font&gt; k = 0; k &amp;lt; persons.length - 1; k++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;if&lt;/font&gt; (persons[k + 1].getName(index).compareTo(persons[k].getName(index)) &amp;lt;= 0) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Person buf = persons[k];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;persons[k] = persons[k + 1];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;persons[k + 1] = buf;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;/blockquote&gt;  На первый взгляд, оба решения совершенно правильные. Одно из них использует библиотечную функцию сортировки, а второе реализует алгоритм сортировки пузырьком. Но оказывается, что своё решение обладает серьезным недостатком, который может повлечь неприятные последствия в реальном коде. Каким? Не скажу! Это задачка для самостоятельной работы :). Ответы просьба писать в комментариях белым шрифтом.  &lt;br /&gt; &lt;b&gt;&lt;br /&gt;2. Свое колесо катится медленнее.&lt;/b&gt;     В примере из первого пункта используется сортировка пузырьком. Как известно, она выполняется за квадратичное время. А стандартная сортировка использует         алгоритм merge sort, обладающий сложностью N*log(N), что работает значительно быстрее. Этот пример не доказывает все случаи, но всё же, в большинстве случаев самописный код работает медленнее библиотечного. &lt;br /&gt; &lt;br /&gt;&lt;b&gt;3. Свой код дороже поддерживать.&lt;/b&gt; Код своих библиотек так или иначе придется поддерживать. Потребуется рефакторинг, доработка, отимизация, отладка с чашкой кофе в три ночи. А использование готовых библиотек позволяет - только задумайтесь - перебросить разработку части функционала на сторонних (часто более надежных) разработчиков. &lt;br /&gt;&lt;b&gt;&lt;br /&gt;4. Знание стандартных библиотек поможет тебе легче понимать чужой код. &lt;/b&gt;Ведь стандартные библиотеки на то и стандартны, что их используют разные команды. &lt;br /&gt; &lt;b&gt;&lt;br /&gt;5. Модули, использующие стандартные библиотеки и интерфейсы, проще интегрируются.&lt;/b&gt; Интеграция модулей включает обмен данными. Если данные не станадртизованы, то придется писать конвертеры. Например, вы хотите соединить в своём проекте библиотеку для работы с http соединениями &lt;code&gt;org.apache.commons.httpclient.*&lt;/code&gt; и библиотеку для работы с xml &lt;code&gt;javax.xml.parsers.*&lt;/code&gt;. Гарантирую головную боль, связанную с тем, что в этих библиотеках используется разный класс для описания URL (&lt;code&gt;java.net.URL&lt;/code&gt; и &lt;code&gt;org.apache.commons.httpclient.HttpURL&lt;/code&gt;)  &lt;br /&gt; &lt;b&gt;&lt;br /&gt;6. Разработчики библиотек часто лучше тебя знают, в чем ты нуждаешься. &lt;/b&gt;Это похоже на теорию заговора? - Вовсе нет. Стандарты в мире java принимаются &lt;a href="http://jcp.org"&gt;консорциумом(en)&lt;/a&gt;, а, значит, принятые решения подходят большинству команд разработчиков. А раз они подходят почти всем, то наверняка, подойдут и тебе. Здесь можно вспомнить про &lt;a href="http://www.microsoft.com/NET/"&gt;другие(en)&lt;/a&gt; технологии, которые разрабатываются полностью внутри компаний, что может (но не обязательно) сделать их  недостаточно удобными для тебя. &lt;br /&gt;&lt;br /&gt;  Жду от вас новых пунктов к этому списку или камней в мой огород. Приветствуется всё!&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:java_master:902</id>
    <link rel="alternate" type="text/html" href="http://java-master.livejournal.com/902.html"/>
    <link rel="self" type="text/xml" href="http://java-master.livejournal.com/data/atom/?itemid=902"/>
    <title>Оптимизируй с умом</title>
    <published>2008-06-28T11:59:32Z</published>
    <updated>2008-06-30T09:52:47Z</updated>
    <category term="оптимизация"/>
    <content type="html">Допустим, я изучил новый язык программирования. Пусть это будет ... Java. Я уже прочитал книжку неизвестного автора "введение в Java", умею создавать приложение "hello world", и даже читать строчки из одного файла и записывать их в другой. Куда мне теперь стремиться как разработчику? Какие умения нужно развивать и какие характеристики программ улучшать? Для того, чтобы ответить на эти вопросы, нужно сформулировать критерии хорошей программы:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Хорошая читаемость кода&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Безошибочность&lt;/li&gt;&lt;li&gt;Компактность кода&lt;/li&gt;&lt;li&gt;Высокая производительность&lt;/li&gt;&lt;li&gt;Невысокие требования к оперативной памяти&lt;/li&gt;&lt;li&gt;Небольшой объем исполнимого кода на диске &lt;/li&gt;&lt;/ul&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;div class="ljcut" text="Read more..."&gt;Кому-то (участникам олимпиад по программированию) интересна высокая производительность.&amp;nbsp; Для кого-то (руководители софтверных проектов) важнее безошибочность и поддерживаемость кода. Есть и такие(разработчики для &lt;a&gt;j2me&lt;/a&gt;), кто из кожи вон лезут, чтобы уменьшить расходы памяти. У каждого может быть свое мнение, но все должны знать об общепринятых приоритетах этих критериев. &lt;br /&gt;&lt;br /&gt;Самым важным параметром программы в современном мире коммерческого программирования считается &lt;b&gt;хорошая поддерживаемость(читаемость) кода&lt;/b&gt;. Если код можно поддерживать, то из глючной программы можно сделать безошибочную, из медленной - производительную, из вредительски пожирающей системные ресурсы - программу со скромными требованиями. Кроме того, распространенные схемой разработки ПО, такие как "&lt;a&gt;спиральная модель(en)&lt;/a&gt;" накладывают на код требования хорошей поддерживаемости. &lt;br /&gt;&lt;br /&gt;Следующим по важности критерием является &lt;b&gt;безошибочность&lt;/b&gt;. Здесь, надеюсь, убеждать никого не придется :). Я уже слышу недовольные возгласы вдумчивого читателя: "А как часто безошибочен неподдерживаемый код?". Безошибочный&amp;nbsp; неподдерживаемый код - это такой, который хорошо протестирован, но при этом &lt;strike&gt;никогда&lt;/strike&gt; очень давно не &lt;a&gt;рефакторился.&lt;/a&gt; Кратко: рефакторинг - это процесс повышения читаемости кода. &lt;br /&gt;&lt;br /&gt;И на третье место можно поставить компактность и производительность. То, что эти критерии стоят на третьем месте, не должно умалять их значимости для заинтересованного в профессиональном росте разработчика. Обеспечив хорошую поддерживаемость и корректность кода, нужно позаботиться и о нервной системе пользователя. А пользователь, как известно, очень не любит ждать. &lt;br /&gt;Замечено, что &lt;i&gt;почти любая неалгоритмическая&lt;/i&gt; оптимизация приводит к снижению читаемости кода. &lt;br /&gt;&lt;br /&gt;Рассмотрим для примера&amp;nbsp; график:&lt;br /&gt;&lt;a&gt;&lt;img src="http://chart.apis.google.com/chart?cht=lc&amp;amp;chd=t:90,85,70,65,50,30,25,20&amp;amp;chco=008000&amp;amp;chls=2.0,4.0,1.0&amp;amp;chs=400x250&amp;amp;chxt=x,y&amp;amp;chxl=0:%7C%7Cslow%7Coptimum%7Cfast%7C%7C1:%7C%7Cless%20maintainable%7Cmore%20maintainable%7C&amp;amp;chm=o,0000ff,0,1,20,0%7Co,0000ff,0,2,20,0%7Co,0000ff,0,4,20,0%7Ca,ff0000,0,4,20,0%7CV,cccccc,0,3,2,0%7Co,0000ff,0,5,20,0%7Co,0000ff,0,6,20,0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;График показывает зависимость производительности кода от читабельности. Здесь синие кружки означают различные стадии оптимизации кода. Разумная стратегия разработки выглядит так:&lt;br /&gt;1. В процессе разработки придерживаемся максимальной поддерживаемости кода (левый кружок)&lt;br /&gt;2. На конечной стадии разработки начинаем выполнять оптимизацию. При этом из всех возможных оптимизаций выбираем такую, которая гарантированно обеспечивает необходимую производительность(optimum) и при этом является максимально поддерживаемой. Это состояние выделено стрелочкой.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Этот блог будет в основном посвящен обзору приемов достижения&amp;nbsp; перечисленных критериев качества кода. Ссылки на литературу и хорошие примеры кода гарантируются!&amp;nbsp;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:java_master:704</id>
    <link rel="alternate" type="text/html" href="http://java-master.livejournal.com/704.html"/>
    <link rel="self" type="text/xml" href="http://java-master.livejournal.com/data/atom/?itemid=704"/>
    <title>Тест: являешься ли ты моим читателем?</title>
    <published>2008-06-27T22:44:54Z</published>
    <updated>2008-06-28T12:31:28Z</updated>
    <category term="обзор"/>
    <category term="ссылки"/>
    <content type="html">Добрый день, дорогой читатель!&lt;br /&gt;&lt;br /&gt;Это первая запись в моем блоге, посвященном разработке на платформе Java. Сначала я хочу пояснить, кому может быть интересен этот блог.&lt;br /&gt;&lt;br /&gt;Мой читатель :&lt;br /&gt;* разработчик ПО или соболезнующий разработчикам ПО&lt;img align="right" src="http://www.antigreen.org/vadim/ProgLanguageComparison/java-coffee-wait.jpg" alt="" /&gt;&lt;br /&gt;* владеет основами программирования на java или другом с-подобном языке.&lt;br /&gt;* не думает, что &lt;a href="http://ru.wikipedia.org/wiki/Объектно-ориентированное_программирование"&gt;ООП&lt;/a&gt; - это &lt;a href="http://ru.wikipedia.org/wiki/Организация_освобождения_Палестины"&gt;организация освобождения Палестины&lt;/a&gt;&lt;br /&gt;* интересуется вещами, выходящими за рамки учебников&lt;br /&gt;* любит оптимизировать и автоматизировать свои ежедневные задачи&lt;br /&gt;&lt;br /&gt;Если для тебя хотя бы три из пяти пунктов совпали, то нам по пути! :)&lt;br /&gt;&lt;br /&gt;Часто для того, чтобы объяснить, чем блог является, проще указать, чем он не является:&lt;br /&gt;* Это НЕ &lt;a&gt;форум о java&lt;/a&gt;, алгоритмах и прочем IT&lt;br /&gt;* Это НЕ &lt;a href="http://anatolix.naumen.ru/Books/Java?v=pcq"&gt;учебник по Java&lt;/a&gt;&lt;br /&gt;* Это НЕ &lt;a href="http://java.sun.com/docs/books/tutorial/"&gt;обзор Java технологий&lt;/a&gt; в чистом виде&lt;br /&gt;&lt;br /&gt;Поздравляю! Эту строчку читают те самые стойкие из вас, кто не ушел гулять по предыдущим ссылкам. Обещаю за это каждого вознаградить сполна! &lt;br /&gt;&lt;br /&gt;До новых встреч!</content>
  </entry>
</feed>
