<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1958886800716997908</id><updated>2011-12-29T10:52:50.886+03:00</updated><category term='scanner'/><category term='google wave'/><category term='авторизация'/><category term='xpp'/><category term='reflection'/><category term='мысли'/><category term='extgwt'/><category term='scala'/><category term='proxy'/><category term='jdbc'/><category term='рекурсия'/><category term='ловушки'/><category term='mysql'/><category term='java'/><category term='clojure'/><category term='swing'/><category term='axapta'/><category term='ajax'/><category term='.NET C#'/><category term='gwt-rpc'/><category term='Должностные лица'/><category term='пример'/><category term='robot'/><category term='gwt'/><category term='шаблоны'/><category term='ввод'/><category term='кортеж'/><category term='gae'/><category term='gui'/><category term='Локализация'/><category term='Отчеты'/><category term='пятничная хрень'/><category term='fp on jvm'/><category term='rtti'/><category term='QueryRun'/><category term='md5'/><category term='декорация'/><title type='text'>OZKA's Dev Journal</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-2200902323775630548</id><published>2010-11-15T15:23:00.005+02:00</published><updated>2010-11-15T15:47:19.634+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fp on jvm'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Небольшая задача на списки в Scala</title><content type='html'>На одном форуме студент обратился с просьбой помочь в реализации задания на Java. Ссылку я приводить не буду, так как по ряду причин его вопрос до сих пор не закрыт, но сама задача показалась мне неплохим поводом немного попрактиковаться со списками в Scala. Звучит она следующим образом: имеется таблица с номерами строк и столбцов, ячейки таблицы содержат числа. Требуется на вход программе подать шаблон, например: "1-2-3-2", данный шаблон нужно разобрать и превратить в набор координат: (1-2), (2-3), (3-2). Для каждой координаты прочитать число из таблицы и рассчитать их сумму. В результате у меня получился следующий код:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style='color: #000083; font-weight: bold'&gt;object&lt;/span&gt; Appl {&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; table &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; Map(&lt;span style='color: blue'&gt;1&lt;/span&gt;-&amp;gt;Map(&lt;span style='color: blue'&gt;1&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;0&lt;/span&gt;, &lt;span style='color: blue'&gt;2&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;5&lt;/span&gt;, &lt;span style='color: blue'&gt;3&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;6&lt;/span&gt;, &lt;span style='color: blue'&gt;4&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;7&lt;/span&gt;),&lt;br /&gt;                  &lt;span style='color: blue'&gt;2&lt;/span&gt;-&amp;gt;Map(&lt;span style='color: blue'&gt;1&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;5&lt;/span&gt;, &lt;span style='color: blue'&gt;2&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;0&lt;/span&gt;, &lt;span style='color: blue'&gt;3&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;8&lt;/span&gt;, &lt;span style='color: blue'&gt;4&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;9&lt;/span&gt;),&lt;br /&gt;                  &lt;span style='color: blue'&gt;3&lt;/span&gt;-&amp;gt;Map(&lt;span style='color: blue'&gt;1&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;6&lt;/span&gt;, &lt;span style='color: blue'&gt;2&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;8&lt;/span&gt;, &lt;span style='color: blue'&gt;3&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;0&lt;/span&gt;, &lt;span style='color: blue'&gt;4&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;4&lt;/span&gt;),&lt;br /&gt;                  &lt;span style='color: blue'&gt;4&lt;/span&gt;-&amp;gt;Map(&lt;span style='color: blue'&gt;1&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;7&lt;/span&gt;, &lt;span style='color: blue'&gt;2&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;9&lt;/span&gt;, &lt;span style='color: blue'&gt;3&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;4&lt;/span&gt;, &lt;span style='color: blue'&gt;4&lt;/span&gt;-&amp;gt;&lt;span style='color: blue'&gt;0&lt;/span&gt;))&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; separator &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;"-"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; lookupValue(table&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Map&lt;/span&gt;[&lt;span style='color: #000083; font-weight: bold'&gt;Int&lt;/span&gt;, &lt;span style='color: #000083; font-weight: bold'&gt;Map&lt;/span&gt;[&lt;span style='color: #000083; font-weight: bold'&gt;Int&lt;/span&gt;, &lt;span style='color: #000083; font-weight: bold'&gt;Int&lt;/span&gt;]], x&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Int&lt;/span&gt;, y&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Int&lt;/span&gt;) &lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Int&lt;/span&gt; = table.get(y).get(x)&lt;br /&gt;  &lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; compute(path&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;String&lt;/span&gt;) &lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Int&lt;/span&gt; = {&lt;br /&gt;&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;try&lt;/span&gt; {&lt;br /&gt;      &lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; list &lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;List&lt;/span&gt;[&lt;span style='color: #000083; font-weight: bold'&gt;Int&lt;/span&gt;] &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; path.split(separator).toList map {cur &lt;span style='color: #000083; font-weight: bold'&gt;=&amp;gt;&lt;/span&gt; Integer.parseInt(cur)}&lt;br /&gt;  &lt;br /&gt;      list.zip(list.tail) map {cur &lt;span style='color: #000083; font-weight: bold'&gt;=&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;lookupValue(table, cur._1, cur._2)} reduceRight {&lt;span style='color: #000083; font-weight: bold'&gt;_&lt;/span&gt; + _}&lt;br /&gt;    }&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;catch&lt;/span&gt; {&lt;br /&gt;      &lt;span style='color: #000083; font-weight: bold'&gt;case&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;_&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;=&amp;gt;&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: blue'&gt;0&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; main(args&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Array&lt;/span&gt;[&lt;span style='color: #000083; font-weight: bold'&gt;String&lt;/span&gt;]) &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;new&lt;/span&gt; Form(table).run&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Если посмотреть на полученный код, то работает он следующим образом: берется строка-шаблон, превращается в список чисел в строковом формате, далее список превращается в числовой формат. Объединив полученный список с самим собой, за исключением первого элементы мы получаем список из пар "координат". Проходя по этому списку, каждая пара координат заменяется на соответствующее ей значение из таблицы, все это снова записывается в список, который в результате содержит значения и в завершении мы просто суммируем полученный набор чисел.&lt;br /&gt;&lt;br /&gt;Разберем происходящее в методе compute пошагово.&lt;br /&gt;&lt;br /&gt;Взять входную строку - шаблон, превратить ее в массив строк на основе указанного разделителя и преобразовать полученный массив в список: &lt;i&gt;...&lt;b&gt; path.split(separator).toList&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Над каждым элементом списка который, после предыдущего шага, представляет собой список чисел в строковом формате, провести преобразование строки в число: &lt;i&gt;... &lt;b&gt;map {cur =&gt; Integer.parseInt(cur)}&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Объединить полученный список с самим собой, исключив первый элемент:  &lt;i&gt;&lt;b&gt;list.zip(list.tail)&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Результатом предыдущей операции будет список пар координат(кортежей?), каждую пару мы заменяем на ее значение в таблице значений: &lt;i&gt;... &lt;b&gt;map {cur =&gt;  lookupValue(table, cur._1, cur._2)}&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;В завершении, полученный список значений последовательно суммируем: &lt;i&gt;...&lt;b&gt; reduceRight {_ + _}&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Все это завернуто в try/catch на случай подачи на вход неверных данных, которые алгоритм не сможет превратить в нужную для расчета структуру. В данном случае подробности ошибок не разбираются и в случае их возникновения мы просто возвращаем 0.&lt;br /&gt;&lt;br /&gt;Итого, на мой субъективный взгляд, получился компактный и симпатичный код, правда он может показаться слега непривычным тем, кто только осваивает язык, как и я :)&lt;br /&gt;&lt;br /&gt;Рабочий пример целиком &lt;a href="https://gist.github.com/df5f435a36356f18cc28"&gt;тут&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-2200902323775630548?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/2200902323775630548/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=2200902323775630548' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/2200902323775630548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/2200902323775630548'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/11/scala.html' title='Небольшая задача на списки в Scala'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-5639290728337942997</id><published>2010-10-21T18:00:00.006+03:00</published><updated>2010-10-26T23:06:36.001+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ловушки'/><category scheme='http://www.blogger.com/atom/ns#' term='пример'/><category scheme='http://www.blogger.com/atom/ns#' term='fp on jvm'/><category scheme='http://www.blogger.com/atom/ns#' term='clojure'/><category scheme='http://www.blogger.com/atom/ns#' term='декорация'/><title type='text'>Декорация функций в Clojure</title><content type='html'>Данная заметка родилась по мотивам статьи &lt;a href="http://zahardzhan.github.com/2010/clojure-hooks.html"&gt;"Ловушки для Clojure"&lt;/a&gt;. Недавно, читая на sql.ru очередное обсуждение языков программирования, я наткнулся на интересную дискуссию о &lt;a href="http://sql.ru/forum/actualthread.aspx?tid=659392&amp;pg=-1&amp;hl=scala#7177413"&gt;декораторах функций и методов&lt;/a&gt;. Предыдущая заметка про Scala появилась в результате попытки найти подобную функциональность в этом замечательном языке. Судя по собственным экспериментам, штатными средствами этого добиться нельзя, а поиск в Google отсылает к каким-то очень уж нетривиальным подходам, которые мой мозг &lt;strike&gt;одинэсника&lt;/strike&gt; прикладного программиста отказывается воспринимать. В свою очередь тот эффект который я искал в Scala можно успешно проделать в Clojure. Ниже будет небольшой пример демонстрации с краткими пояснениями.&lt;br /&gt;&lt;br /&gt;Предположим что нам нужно рассчитать зарплату трех наших сотрудников, например, программистов. Зарплата каждого из них складывается из ставки(оклада) и бонусной части. Ниже приведен код, который это делает.&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; developer_rate &lt;span style='color:#008000; '&gt;60000.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; tax_factor &lt;span style='color:#008000; '&gt;0.87&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;defn&lt;/span&gt; calc_salary &lt;span style='color:#808030; '&gt;[&lt;/span&gt;rate bonus&lt;span style='color:#808030; '&gt;]&lt;/span&gt; &lt;br /&gt;  &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;+&lt;/span&gt; rate bonus&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; mike_salary &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;calc_salary&lt;/span&gt; developer_rate &lt;span style='color:#008000; '&gt;2500.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; vasya_salary &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;calc_salary&lt;/span&gt; developer_rate &lt;span style='color:#008000; '&gt;3000.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; alex_salary &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;calc_salary&lt;/span&gt; developer_rate &lt;span style='color:#008000; '&gt;0.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Теперь в наш код необходимо добавить удержание налога в виде 13%. В принципе мы могли бы сразу написать функцию расчета зарплаты следующим образом:&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;defn&lt;/span&gt; calc_salary &lt;span style='color:#808030; '&gt;[&lt;/span&gt;rate bonus&lt;span style='color:#808030; '&gt;]&lt;/span&gt; &lt;br /&gt;  &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;*&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;+&lt;/span&gt; rate bonus&lt;span style='color:#808030; '&gt;)&lt;/span&gt; tax_factor&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Однако есть одна незадача. Допустим одному из наших программистов довелось работать в чудо-граде Сколково и вычитать с него налог нам не требуется :) Перепишем наш механизм расчета используя "хуки" библиотеки, ссылка на которую есть в начале заметки. Теперь наш код будет выглядеть следующим образом:&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; developer_rate &lt;span style='color:#008000; '&gt;60000.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; tax_factor &lt;span style='color:#008000; '&gt;0.87&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;defn&lt;/span&gt; calc_salary &lt;span style='color:#808030; '&gt;[&lt;/span&gt;rate bonus&lt;span style='color:#808030; '&gt;]&lt;/span&gt; &lt;br /&gt;  &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;+&lt;/span&gt; rate bonus&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#696969; '&gt;;;(defn calc_salary [rate bonus] &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#696969; '&gt;;;  (* (+ rate bonus) tax_factor))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;defn&lt;/span&gt; taxation &lt;span style='color:#808030; '&gt;[&lt;/span&gt;func rate bonus&lt;span style='color:#808030; '&gt;]&lt;/span&gt; &lt;br /&gt;  &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;*&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;func&lt;/span&gt; rate bonus&lt;span style='color:#808030; '&gt;)&lt;/span&gt; tax_factor&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;add-hook&lt;/span&gt; &lt;span style='color:#400000; '&gt;:around&lt;/span&gt; &lt;span style='color:#800080; '&gt;#'calc_salary&lt;/span&gt; &lt;span style='color:#400000; '&gt;:taxation&lt;/span&gt; taxation&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; mike_salary &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;calc_salary&lt;/span&gt; developer_rate &lt;span style='color:#008000; '&gt;2500.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; vasya_salary &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;calc_salary&lt;/span&gt; developer_rate &lt;span style='color:#008000; '&gt;3000.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;remove-hook&lt;/span&gt; &lt;span style='color:#400000; '&gt;:around&lt;/span&gt;  &lt;span style='color:#800080; '&gt;#'calc_salary&lt;/span&gt; &lt;span style='color:#400000; '&gt;:taxation&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; alex_salary &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;calc_salary&lt;/span&gt; developer_rate &lt;span style='color:#008000; '&gt;0.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Функция &lt;i&gt;add-hook&lt;/i&gt; добавила "перехватчик вызова функции" &lt;i&gt;calc_salary&lt;/i&gt;, а перед расчетом нашего счастливого сотрудника из Сколково, мы удалили данный "хук" и не стали вычитать из него налоги. Подробное описание, опять же, смотреть по ссылке на статью в начале этого поста. А ниже еще пара возможностей добавлять функциям поведение на лету.&lt;br /&gt;&lt;br /&gt;Напишем функцию которая печатает ставку программиста, а затем дополним эту функцию выводом еще пары значений, налогового коэффициента и суммы к выдачи после вычета налога:&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;defn&lt;/span&gt; print_rate &lt;span style='color:#808030; '&gt;[&lt;/span&gt;rate&lt;span style='color:#808030; '&gt;]&lt;/span&gt;&lt;br /&gt;  &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;println&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;str&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Rate: "&lt;/span&gt; rate&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;defn&lt;/span&gt; print_tax_factor &lt;span style='color:#808030; '&gt;[&lt;/span&gt;dummy_rate&lt;span style='color:#808030; '&gt;]&lt;/span&gt;&lt;br /&gt;  &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;println&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;str&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Tax factor: "&lt;/span&gt; tax_factor&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;defn&lt;/span&gt; print_rate_excl_tax &lt;span style='color:#808030; '&gt;[&lt;/span&gt;rate&lt;span style='color:#808030; '&gt;]&lt;/span&gt; &lt;br /&gt;  &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;println&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;str&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"NET value: "&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;*&lt;/span&gt; rate tax_factor&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;add-hook&lt;/span&gt; &lt;span style='color:#400000; '&gt;:before&lt;/span&gt; &lt;span style='color:#800080; '&gt;#'print_rate&lt;/span&gt; &lt;span style='color:#400000; '&gt;:print_tax_factor&lt;/span&gt; print_tax_factor&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;add-hook&lt;/span&gt; &lt;span style='color:#400000; '&gt;:after&lt;/span&gt; &lt;span style='color:#800080; '&gt;#'print_rate&lt;/span&gt; &lt;span style='color:#400000; '&gt;:print_rate_excl_tax&lt;/span&gt; print_rate_excl_tax&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Теперь мы можем вызвать в REPL например следующий код &lt;i&gt;(print_rate 10000)&lt;/i&gt; и проверить результат. &lt;br /&gt;&lt;br /&gt;В заключение. Естественно такие расчеты можно выполнить массой других способов, все что выше всего лишь простое пояснение возможности изменять реализацию функций в Clojure на лету. На всякий случай хочу сказать, что в Clojure я по пятибалльной шкале разбираюсь на уровне 0 с каким-то минимальным значением после запятой, в общем учусь, так что если сильно что напутал/наврал, приношу свои извинения. &lt;a href="https://gist.github.com/f12934de9897e415702f"&gt;Код целиком на gitgist&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-5639290728337942997?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/5639290728337942997/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=5639290728337942997' title='Комментарии: 5'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/5639290728337942997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/5639290728337942997'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/10/clojure.html' title='Декорация функций в Clojure'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-5146955546751185866</id><published>2010-10-18T22:43:00.007+03:00</published><updated>2010-10-26T23:07:17.436+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='пример'/><category scheme='http://www.blogger.com/atom/ns#' term='fp on jvm'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Неявные преобразования типов в Scala</title><content type='html'>Предположим что у нас есть класс человек(Human), но по каким либо причинам мы не можем вносить изменения в данный класс, при этом нам хочется наделить его дополнительным поведением. Предположим что наш человек должен на работе выполнять некие действия сотрудника, а дома отдыхать. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style='color: #000083; font-weight: bold'&gt;package&lt;/span&gt; implicitconversions&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color: #000083; font-weight: bold'&gt;case&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;class&lt;/span&gt; Human(&lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; name&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;String&lt;/span&gt;, &lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; salary&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Double&lt;/span&gt;) {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; greeting &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; println(&lt;span style='color: #008200; font-weight: bold'&gt;"Hello,&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;my&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;name&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;is&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;"&lt;/span&gt; + name)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color: #000083; font-weight: bold'&gt;class&lt;/span&gt; Worker(&lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; h &lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Human&lt;/span&gt;) {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; doJob&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; println(h.name + &lt;span style='color: #008200; font-weight: bold'&gt;"&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;do&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;his&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;job"&lt;/span&gt;)&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; showSalary &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; println (h.name + &lt;span style='color: #008200; font-weight: bold'&gt;"&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;salary&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;is&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;"&lt;/span&gt; + h.salary)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style='color: #000083; font-weight: bold'&gt;class&lt;/span&gt; Pastime() {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; watchTV &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; println(&lt;span style='color: #008200; font-weight: bold'&gt;"Watching&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;TV"&lt;/span&gt;)&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; walk &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; println(&lt;span style='color: #008200; font-weight: bold'&gt;"Walking..."&lt;/span&gt;)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color: #000083; font-weight: bold'&gt;object&lt;/span&gt; JobEnviroment {&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;implicit&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; human2Worker(h&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Human&lt;/span&gt;) &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;new&lt;/span&gt; Worker(h)&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; in(h&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Human&lt;/span&gt;) {&lt;br /&gt;    h.doJob&lt;br /&gt;    h.showSalary&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style='color: #000083; font-weight: bold'&gt;object&lt;/span&gt; HomeEnviroment {&lt;br /&gt;&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;implicit&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; human2Pastime(h&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Human&lt;/span&gt;) &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;new&lt;/span&gt; Pastime()&lt;br /&gt;&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; in(h&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Human&lt;/span&gt;) {&lt;br /&gt;     h.watchTV&lt;br /&gt;     h.walk&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style='color: #000083; font-weight: bold'&gt;object&lt;/span&gt; DemoAppl {&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; complexDemo &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; {&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;import&lt;/span&gt; HomeEnviroment._&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;import&lt;/span&gt; JobEnviroment._&lt;br /&gt;&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; h &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;new&lt;/span&gt; Human(&lt;span style='color: #008200; font-weight: bold'&gt;"Pete"&lt;/span&gt;, &lt;span style='color: blue'&gt;40000&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;    h.greeting&lt;br /&gt;    h.doJob&lt;br /&gt;    h.showSalary&lt;br /&gt;    h.watchTV&lt;br /&gt;    h.walk&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; errorDemo {&lt;br /&gt;&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; h &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;new&lt;/span&gt; Human(&lt;span style='color: #008200; font-weight: bold'&gt;"Steve"&lt;/span&gt;, &lt;span style='color: blue'&gt;15000&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;    h.greeting&lt;br /&gt;    &lt;span style='color: #7E7E7E'&gt;//Error&lt;/span&gt; &lt;span style='color: #7E7E7E'&gt;--&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color: #7E7E7E'&gt;//h.doJob&lt;/span&gt;&lt;br /&gt;    &lt;span style='color: #7E7E7E'&gt;//h.showSalary&lt;/span&gt;&lt;br /&gt;    &lt;span style='color: #7E7E7E'&gt;//h.watchTV&lt;/span&gt;&lt;br /&gt;    &lt;span style='color: #7E7E7E'&gt;//h.walk&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color: #7E7E7E'&gt;//&lt;/span&gt; &lt;span style='color: #7E7E7E'&gt;&amp;lt;--&lt;/span&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;def&lt;/span&gt; main(args&lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Array&lt;/span&gt;[&lt;span style='color: #000083; font-weight: bold'&gt;String&lt;/span&gt;]) &lt;span style='color: #000083; font-weight: bold'&gt;:&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;Unit&lt;/span&gt; = {&lt;br /&gt;    println(&lt;span style='color: #008200; font-weight: bold'&gt;"Scala&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;Implicit&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;Conversions"&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;val&lt;/span&gt; h &lt;span style='color: #000083; font-weight: bold'&gt;=&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;new&lt;/span&gt; Human(&lt;span style='color: #008200; font-weight: bold'&gt;"Vasya"&lt;/span&gt;, &lt;span style='color: blue'&gt;25000&lt;/span&gt;)&lt;br /&gt;    h.greeting&lt;br /&gt;&lt;br /&gt;    JobEnviroment.in(h)&lt;br /&gt;    HomeEnviroment.in(h)&lt;br /&gt;&lt;br /&gt;    complexDemo&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Как видно из примера выше, конструкция &lt;b&gt;implicit def&lt;/b&gt; указывает Scala компилятору, что в данном случае класс Human приобретает новые методы: класса Worker в контексте объекта JobEnviroment и Pastime в HomeEnviroment. В методе complexDemo мы импортируем оба определения неявных преобразований и можем выполнить все дополнительные методы одновременно.&lt;br /&gt;&lt;br /&gt;Данная возможность представляет собой аналоги расширяющих методов языка C#, а так же напоминает облегченную версию прототипов "JavaScript", впрочем думаю что злоупотреблять ее использованием наверное не стоит, так как это может сильно запутать код.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-5146955546751185866?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/5146955546751185866/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=5146955546751185866' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/5146955546751185866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/5146955546751185866'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/10/scala.html' title='Неявные преобразования типов в Scala'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-4952376003421433393</id><published>2010-08-27T15:18:00.003+03:00</published><updated>2010-08-27T15:37:33.768+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='кортеж'/><category scheme='http://www.blogger.com/atom/ns#' term='пример'/><title type='text'>Как в java вернуть из метода больше одного значения?</title><content type='html'>Довольно регулярно в интернет форумах от новичков можно услышать подобный вопрос. В появившемся гораздо позже языке C# эта задача решается с помощью ключевых слов &lt;a href ="http://www.weblibrary.biz/c-sharp/metod/out_ref"&gt;ref и out&lt;/a&gt;. В Java элементарные типы(int, boolean, double e.t.c.) всегда передаются по значению. "Оболочки типов" (Integer, Boolean, Double e.t.c.), а так же класс String, несмотря на то что передаются по ссылке, являются неизменяемыми классами (Immutable), таким образом, любая операция по присвоению переменным этих типов нового значения создает в памяти новый объект. Из этого следует, что передача переменной такого типа в метод и ее изменение внутри метода никак не повлияет на значение хранящееся в этой переменной за пределами метода. &lt;br /&gt;&lt;br /&gt;Давайте представим ситуацию что нам все же потребовалось вернуть из метода больше одного значения, например, у нас имеется метод который должен рассчитывать и возвращать: имя сотрудника и его зарплату. Для этого воспользуемся структурой именуемой в программировании &lt;a href="http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D1%80%D1%82%D0%B5%D0%B6#.D0.92_.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.B8"&gt;кортеж&lt;/a&gt;. Создадим класс, способный хранить пару значений любого нужного нам типа данных:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style='color: #000083; font-weight: bold'&gt;package&lt;/span&gt; adv;&lt;br /&gt;&lt;br /&gt;&lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;class&lt;/span&gt; TupleAB&amp;lt;A, B&amp;gt; {&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;private&lt;/span&gt; A a;&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;private&lt;/span&gt; B b;&lt;br /&gt; &lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; TupleAB() {&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; TupleAB(A a, B b) {&lt;br /&gt;  setA(a);&lt;br /&gt;  setB(b);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; A getA() {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; a;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;void&lt;/span&gt; setA(A a) {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;this&lt;/span&gt;.a = a;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; B getB() {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; b;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;void&lt;/span&gt; setB(B b) {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;this&lt;/span&gt;.b = b;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; String toString() {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;"("&lt;/span&gt; + a + &lt;span style='color: #008200; font-weight: bold'&gt;",&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;"&lt;/span&gt; + b + &lt;span style='color: #008200; font-weight: bold'&gt;")"&lt;/span&gt;;&lt;br /&gt; }&lt;br /&gt;  &lt;br /&gt; @Override&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;int&lt;/span&gt; hashCode() {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;final&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;int&lt;/span&gt; prime = &lt;span style='color: blue'&gt;31&lt;/span&gt;;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;int&lt;/span&gt; result = &lt;span style='color: blue'&gt;1&lt;/span&gt;;&lt;br /&gt;  result = prime * result + ((a == &lt;span style='color: #000083; font-weight: bold'&gt;null&lt;/span&gt;) ? &lt;span style='color: blue'&gt;0&lt;/span&gt; : a.hashCode());&lt;br /&gt;  result = prime * result + ((b == &lt;span style='color: #000083; font-weight: bold'&gt;null&lt;/span&gt;) ? &lt;span style='color: blue'&gt;0&lt;/span&gt; : b.hashCode());&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; result;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @SuppressWarnings(&lt;span style='color: #008200; font-weight: bold'&gt;"unchecked"&lt;/span&gt;)&lt;br /&gt; @Override&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;boolean&lt;/span&gt; equals(Object obj) {&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (&lt;span style='color: #000083; font-weight: bold'&gt;this&lt;/span&gt; == obj)&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;true&lt;/span&gt;;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (obj == &lt;span style='color: #000083; font-weight: bold'&gt;null&lt;/span&gt;)&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;false&lt;/span&gt;;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (getClass() != obj.getClass())&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;false&lt;/span&gt;;&lt;br /&gt;  TupleAB&amp;lt;A, B&amp;gt; other = (TupleAB&amp;lt;A, B&amp;gt;) obj;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (a == &lt;span style='color: #000083; font-weight: bold'&gt;null&lt;/span&gt;) {&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (other.a != &lt;span style='color: #000083; font-weight: bold'&gt;null&lt;/span&gt;)&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;false&lt;/span&gt;;&lt;br /&gt;  } &lt;span style='color: #000083; font-weight: bold'&gt;else&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (!a.equals(other.a))&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;false&lt;/span&gt;;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (b == &lt;span style='color: #000083; font-weight: bold'&gt;null&lt;/span&gt;) {&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (other.b != &lt;span style='color: #000083; font-weight: bold'&gt;null&lt;/span&gt;)&lt;br /&gt;    &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;false&lt;/span&gt;;&lt;br /&gt;  } &lt;span style='color: #000083; font-weight: bold'&gt;else&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;if&lt;/span&gt; (!b.equals(other.b))&lt;br /&gt;   &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;false&lt;/span&gt;;&lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;true&lt;/span&gt;;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br /&gt;Ниже приведен пример использования:&lt;br /&gt;&lt;pre&gt;&lt;span style='color: #000083; font-weight: bold'&gt;package&lt;/span&gt; adv;&lt;br /&gt;&lt;br /&gt;&lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;class&lt;/span&gt; TupleExample {&lt;br /&gt;&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;static&lt;/span&gt; TupleAB&amp;lt;String, Double&amp;gt; getEmplSalary() {&lt;br /&gt;  String emplName = &lt;span style='color: #008200; font-weight: bold'&gt;"Гера&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;Кремов"&lt;/span&gt;;&lt;br /&gt;  Double salary&amp;nbsp;&amp;nbsp;&amp;nbsp;= &lt;span style='color: blue'&gt;8.50&lt;/span&gt;;&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;span style='color: #000083; font-weight: bold'&gt;return&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;new&lt;/span&gt; TupleAB&amp;lt;String, Double&amp;gt;(emplName, salary);&lt;br /&gt; }&lt;br /&gt; &lt;span style='color: #000083; font-weight: bold'&gt;public&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;static&lt;/span&gt; &lt;span style='color: #000083; font-weight: bold'&gt;void&lt;/span&gt; main(String[] args) {&lt;br /&gt;  TupleAB&amp;lt;String, Double&amp;gt; emplSalary = getEmplSalary();&lt;br /&gt;  &lt;br /&gt;  System.out.println(emplSalary);&lt;br /&gt;  System.out.println(&lt;span style='color: #008200; font-weight: bold'&gt;"Name:&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style='color: #008200; font-weight: bold'&gt;"&lt;/span&gt; + emplSalary.getA());&lt;br /&gt;  System.out.println(&lt;span style='color: #008200; font-weight: bold'&gt;"Salary:&lt;/span&gt; &lt;span style='color: #008200; font-weight: bold'&gt;"&lt;/span&gt; + emplSalary.getB());&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br/&gt;Аналогичным образом мы можем создать класс для хранения и большего количества переменных.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-4952376003421433393?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/4952376003421433393/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=4952376003421433393' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/4952376003421433393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/4952376003421433393'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/08/java.html' title='Как в java вернуть из метода больше одного значения?'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-115202882653696536</id><published>2010-05-18T14:20:00.000+03:00</published><updated>2010-05-18T14:27:09.784+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gwt-rpc'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='авторизация'/><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>Авторизация через службу User Service в GWT приложениях</title><content type='html'>Cтатья адресована Java программистам начинающим знакомиться с возможностями облачной платформы Google Apps Engine. Так же, я немного напишу про прокол GWT-RPC. Дело в том, что в сфере веб-технологий меня в первую очередь интересуют RIA приложения, а в данный момент технология GWT и производные от нее фреймворки. Несмотря на это, в первой части статьи я постараюсь описать процесс авторизации для тех программистов, кто использует в качестве клиентской части отличные от GWT технологии. Для разработки GWT/GAE приложений я использую Google Eclipse плагин, дальнейший текст построен на предположении что читатель самостоятельно установил и настроил этот плагин, а так же разбирается в основах создания web-приложений на базе технологий Java Servlets &amp; JSP.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ru.enetri.com/2010/05/18/1.html"&gt;Читать дальше на &lt;img src="http://www.enetri.com/images/16x16.png"/&gt; n e t r i...&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;p.s. Почему именно там? Ну во первых их проект так же построен на Google Apps Engine, правда на Python, а во вторых, а почему бы и нет!?!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-115202882653696536?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/115202882653696536/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=115202882653696536' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/115202882653696536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/115202882653696536'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/05/user-service-gwt.html' title='Авторизация через службу User Service в GWT приложениях'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-3482037936240266351</id><published>2010-05-07T18:36:00.000+03:00</published><updated>2010-05-07T18:50:46.229+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='extgwt'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='swing'/><category scheme='http://www.blogger.com/atom/ns#' term='gui'/><title type='text'>Пример вывода данных из БД в таблицу Swing</title><content type='html'>Небольшая предыстория. Честно говоря про swing  я толком больше ничего и не знаю. Данный пример родился на свет после того как в перерыве между чтением Эккеля, я зашел на один Java форум и наткнулся там на многодневную катавасию, где человек пытается сделать примерно тоже самое, но у него ничего не выходит. А гуру раздела дружно над ним прикалываются и рекомендуют не тратить время и возвращаться в Access (: Мне стало интересно, действительно ли это такой сложный процесс, и я набросал данный пример. Небольшое пояснение его работы в комментариях в коде.&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;package&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; test&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Connection&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;DriverManager&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;PreparedStatement&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;ResultSet&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;ResultSetMetaData&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;SQLException&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Types&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Properties&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Vector&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; javax&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;swing&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;JFrame&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; javax&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;swing&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;JScrollPane&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; javax&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;swing&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;JTable&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; javax&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;swing&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;SwingUtilities&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; javax&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;swing&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;table&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;DefaultTableModel&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; ApplMainForm {&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; ApplMainForm() {&lt;br /&gt;                        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;Connection&lt;/span&gt;             conn  = &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;PreparedStatement&lt;/span&gt;   pstmt = &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;ResultSet&lt;/span&gt;            rs    = &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;br /&gt;        DefaultTableModel   dtm   = &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;try&lt;/span&gt; {&lt;br /&gt;                        &lt;br /&gt;             &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;Properties&lt;/span&gt; connInfo = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;Properties&lt;/span&gt;();&lt;br /&gt;            &lt;br /&gt;            connInfo.put(&lt;span style='color:#2a00ff; '&gt;"characterEncoding"&lt;/span&gt;,&lt;span style='color:#2a00ff; '&gt;"UTF8"&lt;/span&gt;);&lt;br /&gt;            connInfo.put(&lt;span style='color:#2a00ff; '&gt;"user"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"usr"&lt;/span&gt;);&lt;br /&gt;            connInfo.put(&lt;span style='color:#2a00ff; '&gt;"password"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"pwd"&lt;/span&gt;);&lt;br /&gt;            &lt;br /&gt;            conn  = &lt;span style='color:#7f0055; font-weight:bold; '&gt;DriverManager&lt;/span&gt;.getConnection(&lt;span style='color:#2a00ff; '&gt;"jdbc:mysql://localhost/test?"&lt;/span&gt;, connInfo);            &lt;br /&gt;            pstmt = conn.prepareStatement(&lt;span style='color:#2a00ff; '&gt;"select * from EmplTable limit 1, 100;"&lt;/span&gt;);&lt;br /&gt;            dtm   = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; DefaultTableModel();&lt;br /&gt;            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(pstmt.execute()) {&lt;br /&gt;                rs = pstmt.getResultSet();                                &lt;br /&gt;                &lt;br /&gt;                &lt;span style='color:#3f7f59; '&gt;//Формируем заголовки столбцов из названия полей --&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;ResultSetMetaData&lt;/span&gt; rsmd = rs.getMetaData();                &lt;br /&gt;                &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; col = 1; col &amp;lt;= rsmd.getColumnCount(); col++)&lt;br /&gt;                    dtm.addColumn(rsmd.getColumnName(col)); &lt;br /&gt;                &lt;span style='color:#3f7f59; '&gt;// &amp;lt;--&lt;/span&gt;&lt;br /&gt;                &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;while&lt;/span&gt; (rs.next()) {&lt;br /&gt;                    &lt;br /&gt;                    &lt;span style='color:#7f0055; font-weight:bold; '&gt;Vector&lt;/span&gt;&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;  row = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;Vector&lt;/span&gt;&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;(); &lt;span style='color:#3f7f59; '&gt;//Строка таблицы&lt;/span&gt;&lt;br /&gt;                    &lt;span style='color:#3f7f59; '&gt;/*Снова с помощью метаданных узнаем количество столбцов &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f7f59; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;* в результате запроса и ниже в switch'е в зависимости &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f7f59; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;* от типа текущего столбца забираем данные из ResultSet`a и пишем в &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f7f59; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;* текущую строку - row. &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f7f59; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;* */&lt;/span&gt;&lt;br /&gt;                    &lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; col = 1; col &amp;lt;= rsmd.getColumnCount(); col++) {                        &lt;br /&gt;                        &lt;br /&gt;                        &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; type = rsmd.getColumnType(col);&lt;br /&gt;                        &lt;br /&gt;                        &lt;span style='color:#7f0055; font-weight:bold; '&gt;switch&lt;/span&gt;(type) {&lt;br /&gt;                        &lt;br /&gt;                            &lt;span style='color:#7f0055; font-weight:bold; '&gt;case&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;Types&lt;/span&gt;.INTEGER :&lt;br /&gt;                                row.add(&lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;Integer&lt;/span&gt;(rs.getInt(col)).toString());&lt;br /&gt;                                &lt;span style='color:#7f0055; font-weight:bold; '&gt;break&lt;/span&gt;;&lt;br /&gt;                                &lt;br /&gt;                            &lt;span style='color:#7f0055; font-weight:bold; '&gt;case&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;Types&lt;/span&gt;.VARCHAR :&lt;br /&gt;                                row.add(rs.getString(col));&lt;br /&gt;                                &lt;span style='color:#7f0055; font-weight:bold; '&gt;break&lt;/span&gt;;&lt;br /&gt;                                &lt;br /&gt;                            &lt;span style='color:#7f0055; font-weight:bold; '&gt;default&lt;/span&gt; :&lt;br /&gt;                                &lt;span style='color:#3f7f59; '&gt;/*В этой моей тестовой таблице всего два типа полей: целое и строка. &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f7f59; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;*Соответственно если в таблице/запросе типов больше, то этот switch &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f7f59; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;*нужно расширить соответствующими типами, а сейчас, в случае если мы &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f7f59; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;*встретим неизвестный коду тип поля, я для наглядности бросаю исключение.                                    &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f7f59; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;* */&lt;/span&gt;&lt;br /&gt;                                &lt;span style='color:#7f0055; font-weight:bold; '&gt;throw&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;Exception&lt;/span&gt;(&lt;span style='color:#2a00ff; '&gt;"Неподдерживаемый тип"&lt;/span&gt;);&lt;br /&gt;                        }&lt;br /&gt;                        &lt;br /&gt;                    }                                    &lt;br /&gt;                    &lt;br /&gt;                    dtm.addRow(row);&lt;br /&gt;                }&lt;br /&gt;            }                                    &lt;br /&gt;        }&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;SQLException&lt;/span&gt; ex) {            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(ex.toString());&lt;br /&gt;            &lt;br /&gt;                        &lt;br /&gt;        } &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;Exception&lt;/span&gt; e) {            &lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;finally&lt;/span&gt; {&lt;br /&gt;            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;try&lt;/span&gt; {&lt;br /&gt;                &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (pstmt != &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;)&lt;br /&gt;                    pstmt.close();&lt;br /&gt;                &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (conn != &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;)&lt;br /&gt;                    conn.close();                &lt;br /&gt;            }&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;SQLException&lt;/span&gt; ex) {                                            &lt;br /&gt;                ex.printStackTrace();&lt;br /&gt;            }                        &lt;br /&gt;            &lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;                                    &lt;br /&gt;        JTable      grid = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; JTable();&lt;br /&gt;        &lt;br /&gt;        grid.setModel(dtm);&lt;br /&gt;        &lt;br /&gt;        JScrollPane jsp  = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; JScrollPane(grid);&lt;br /&gt;        &lt;br /&gt;        JFrame jf = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; JFrame(&lt;span style='color:#2a00ff; '&gt;"Эти фламинго - поклонники свинга(c)Не мой :) "&lt;/span&gt;);&lt;br /&gt;        jf.setSize(640, 480);&lt;br /&gt;        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&lt;br /&gt;        &lt;br /&gt;        jf.add(jsp);        &lt;br /&gt;        jf.setVisible(&lt;span style='color:#7f0055; font-weight:bold; '&gt;true&lt;/span&gt;);        &lt;br /&gt;    }&lt;br /&gt;                                &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; HelloSwing {&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; main(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;[] args) {&lt;br /&gt;        SwingUtilities.invokeLater( &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; Runnable() {&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; run() {                &lt;br /&gt;                    &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; ApplMainForm();                &lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Хотелось бы упомянуть еще один момент. Я часто слышал мнение что использовать Java GUI это "мазохизм", там все очень сложно, криво и через "известное отверстие". Впрочем, есть и другие мнения, говорящие что "надо уметь готовить". Так вот, когда я попытался несколько усложнить этот пример для одного своего эксперимента, разбираясь в устройстве Listener' ов и вообще в этой идее с моделями все это мне показалось очень знакомым. Я и раньше, встречая в интернете код Java GUI замечал его некоторую схожесть с архитектурой используемой в веб-фреймворке ExtGWT, а после того как немного посмотрел самостоятельно, то могу смело выдвинуть предположение, что те кто проектировал ExtGWT делали это, оглядываясь на Swing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-3482037936240266351?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/3482037936240266351/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=3482037936240266351' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/3482037936240266351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/3482037936240266351'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/05/swing.html' title='Пример вывода данных из БД в таблицу Swing'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-4695683398751761746</id><published>2010-05-03T13:46:00.000+03:00</published><updated>2010-05-03T14:00:43.805+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='scanner'/><category scheme='http://www.blogger.com/atom/ns#' term='рекурсия'/><category scheme='http://www.blogger.com/atom/ns#' term='ввод'/><title type='text'>Считываем числовые данные с клавиатуры используя класс Scanner</title><content type='html'>Иногда, отвечая на несложные вопросы на форумах, рождаются небольшие, но законченные примеры. А еще бывает необходимо заглянуть в этот пример, решая какую то свою задачу. Буду периодически постить такие вот маленькие решения. Полностью ветку можно найти &lt;a href="http://www.javatalks.ru/ftopic15927.php"&gt;здесь&lt;/a&gt;. В двух словах, у человека стояла задача считывать с клавиатуры сначала кол-во аргументов, затем, таким же образом, считать сами значения аргументов и произвести над ними какие-то вычисления. Естественно требовалось обработать ситуацию если с клавиатуры ввели неверные данные, например, отрицательное число или вообще символы. &lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;InputMismatchException&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Scanner&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; DigitsEnterException &lt;span style='color:#7f0055; font-weight:bold; '&gt;extends&lt;/span&gt; Exception {&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;private&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;final&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;long&lt;/span&gt; serialVersionUID = 1L;&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; DigitsEnterException() {&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;super&lt;/span&gt;();&lt;br /&gt;    }&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; DigitsEnterException(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; msg) {        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;super&lt;/span&gt;(msg);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; DigitsEnter {&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;private&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; getNum() {&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; getNum(&lt;span style='color:#7f0055; font-weight:bold; '&gt;false&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;private&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; getNum(&lt;span style='color:#7f0055; font-weight:bold; '&gt;boolean&lt;/span&gt; isQtyEnter) {&lt;br /&gt;        Scanner in = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; Scanner(&lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.in);&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; ret = 0;&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;try&lt;/span&gt; {&lt;br /&gt;            ret = in.nextInt();&lt;br /&gt;            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (isQtyEnter &amp;amp;&amp;amp; ret &amp;lt;= 0) {                &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;throw&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; DigitsEnterException(); &lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (InputMismatchException e) {&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"Требуется ввести число"&lt;/span&gt;);            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; getNum(isQtyEnter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (DigitsEnterException e) {&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"Кол-во переменных не может быть равно "&lt;/span&gt; + ret);            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; getNum(isQtyEnter);&lt;br /&gt;        }&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;Exception&lt;/span&gt; e){            &lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; ret;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;        &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; run() {        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"Введите кол-во переменных: "&lt;/span&gt;);&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; qty = getNum(&lt;span style='color:#7f0055; font-weight:bold; '&gt;true&lt;/span&gt;);         &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; arguments[] = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt;[qty];&lt;br /&gt;        &lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; i = 1; i &amp;lt;= qty; i++) {&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"Введите аргумент №"&lt;/span&gt; + i);&lt;br /&gt;            arguments[i - 1] = getNum();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; i = 1; i &amp;lt;= arguments.length; i++) {&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"Aргумент №"&lt;/span&gt; + i + &lt;span style='color:#2a00ff; '&gt;"-&gt; "&lt;/span&gt; + arguments[i - 1]);&lt;br /&gt;        }&lt;br /&gt;                        &lt;br /&gt;    } &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; main(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;[] args) {&lt;br /&gt;        &lt;br /&gt;           &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; DigitsEnter().run();                    &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Если внимательно посмотреть на метод getNum(...), можно видеть что в catch блоках после вывода информации об ошибке происходит рекурсивный вызов той же функции, до тех пор, пока пользователь не введет требуемые данные. Так же, для наглядности логики создан специальный класс исключения несущий сугубо информативные функции.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-4695683398751761746?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/4695683398751761746/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=4695683398751761746' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/4695683398751761746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/4695683398751761746'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/05/scanner.html' title='Считываем числовые данные с клавиатуры используя класс Scanner'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-7191694092768863361</id><published>2010-04-21T18:49:00.000+03:00</published><updated>2010-04-21T23:16:48.228+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='шаблоны'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='proxy'/><title type='text'>Шаблон проектирования "Заместитель"(proxy).</title><content type='html'>&lt;a href="http://ru.wikipedia.org/wiki/Proxy_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)"&gt;Википедия&lt;/a&gt; дает следующее определение: &lt;i&gt;"Предоставляет объект, который контролирует доступ к другому объекту через перехват всех вызовов"&lt;/i&gt;. Ниже будет рассмотрела реализация на примере имитации кэширующего прокси-сервера.&lt;br/&gt; &lt;br /&gt;Схема:&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;img src="http://img-fotki.yandex.ru/get/7/kir-ozer.11/0_719fc_9a7ff2bb_XL.jpg" width="800" height="600" title="" alt="" border="0"/&gt;&lt;br /&gt;Реализация:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;package&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; patterns&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;ArrayList&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;HashMap&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;List&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Map&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Set&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#7f9fbf; font-weight:bold; '&gt;*&lt;/span&gt;&lt;span style='color:#3f5fbf; '&gt; Субъект&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;*/&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;interface&lt;/span&gt; ContentProvider {&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;  getPage(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;    url);&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;boolean&lt;/span&gt; isDinamicPage(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;    url);    &lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#7f9fbf; font-weight:bold; '&gt;*&lt;/span&gt;&lt;span style='color:#3f5fbf; '&gt; Реальный субьект&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;*/&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; WebServer &lt;span style='color:#7f0055; font-weight:bold; '&gt;implements&lt;/span&gt; ContentProvider {&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;private&lt;/span&gt; Map&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;, &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;    siteContent;&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;private&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;List&lt;/span&gt;&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;        dinamicPages;&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; WebServer() {&lt;br /&gt;        siteContent     = WebServer.buildSite();&lt;br /&gt;        dinamicPages    = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; ArrayList&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;();&lt;br /&gt;                &lt;br /&gt;        &lt;span style='color:#3f7f59; '&gt;//�скуственно обозначили динамический контент&lt;/span&gt;&lt;br /&gt;        dinamicPages.add(&lt;span style='color:#2a00ff; '&gt;"news"&lt;/span&gt;);&lt;br /&gt;        dinamicPages.add(&lt;span style='color:#2a00ff; '&gt;"blog"&lt;/span&gt;);&lt;br /&gt;        &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @Override&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; getPage(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; url) {&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.print(&lt;span style='color:#2a00ff; '&gt;"Server"&lt;/span&gt;);&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; siteContent.get(url);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;boolean&lt;/span&gt; isDinamicPage(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; url) {&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (dinamicPages.contains(url))&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;true&lt;/span&gt;;        &lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;false&lt;/span&gt;;    &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#3f5fbf; '&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#7f9fbf; font-weight:bold; '&gt;*&lt;/span&gt;&lt;span style='color:#3f5fbf; '&gt; Простой фабричный метод который строит коллекцию страничек с ключем URL&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;*/&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; Map&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;, &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt; buildSite() {&lt;br /&gt;        Map&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;, &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;    siteContent = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; HashMap&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;, &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;();&lt;br /&gt;        &lt;br /&gt;        siteContent.put(&lt;span style='color:#2a00ff; '&gt;"index"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"index content"&lt;/span&gt;);&lt;br /&gt;        siteContent.put(&lt;span style='color:#2a00ff; '&gt;"customers"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"customers content"&lt;/span&gt;);&lt;br /&gt;        siteContent.put(&lt;span style='color:#2a00ff; '&gt;"contacts"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"contacts content"&lt;/span&gt;);&lt;br /&gt;        siteContent.put(&lt;span style='color:#2a00ff; '&gt;"news"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"news content"&lt;/span&gt;);&lt;br /&gt;        siteContent.put(&lt;span style='color:#2a00ff; '&gt;"blog"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"blog content"&lt;/span&gt;);&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; siteContent;&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#7f9fbf; font-weight:bold; '&gt;*&lt;/span&gt;&lt;span style='color:#3f5fbf; '&gt; Заместитель&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;*/&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; ProxyServer &lt;span style='color:#7f0055; font-weight:bold; '&gt;implements&lt;/span&gt; ContentProvider{&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;private&lt;/span&gt; WebServer            server;&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;private&lt;/span&gt; Map&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;, &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;    cache;&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; ProxyServer() {&lt;br /&gt;        cache = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; HashMap&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;, &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;();&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    @Override&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; getPage(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; url) {&lt;br /&gt;                    &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (server == &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;)&lt;br /&gt;            server = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; WebServer();&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#3f7f59; '&gt;//Динамику забираем напрямую с сервера&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (isDinamicPage(url)) {            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; server.getPage(url);&lt;br /&gt;        }        &lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#3f7f59; '&gt;//Проверяем и обновляем кэш&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (! cache.containsKey(url)) {&lt;br /&gt;            cache.put(url, server.getPage(url));&lt;br /&gt;        }&lt;br /&gt;                        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.print(&lt;span style='color:#2a00ff; '&gt;"+Proxy: "&lt;/span&gt;);&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; cache.get(url);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;boolean&lt;/span&gt; isDinamicPage(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; url) {&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; server.isDinamicPage(url);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; ProxyPattern {&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#3f5fbf; '&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#7f9fbf; font-weight:bold; '&gt;*&lt;/span&gt;&lt;span style='color:#3f5fbf; '&gt; Клиент&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#3f5fbf; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;*/&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; main(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;[] args) {&lt;br /&gt;        &lt;br /&gt;        ContentProvider        provider = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; ProxyServer();&lt;br /&gt;        &lt;br /&gt;        Set&amp;lt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;&gt;     urls = WebServer.buildSite().keySet();&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; i = 1; i &amp;lt; 4; i++) {&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"�терация № "&lt;/span&gt; + i);&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; url: urls) {&lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"["&lt;/span&gt; + provider.getPage(url) + &lt;span style='color:#2a00ff; '&gt;"]"&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"Далее, напряму с сервера"&lt;/span&gt;);&lt;br /&gt;        provider = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; WebServer();&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt;(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; url: urls) {&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"["&lt;/span&gt; + provider.getPage(url) + &lt;span style='color:#2a00ff; '&gt;"]"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Если мы запустим приведенный выше листинг, то получим следующий вывод:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Итерация № 1&lt;br /&gt;Server+Proxy: [index content]&lt;br /&gt;Server[news content]&lt;br /&gt;Server[blog content]&lt;br /&gt;Server+Proxy: [customers content]&lt;br /&gt;Server+Proxy: [contacts content]&lt;br /&gt;Итерация № 2&lt;br /&gt;+Proxy: [index content]&lt;br /&gt;Server[news content]&lt;br /&gt;Server[blog content]&lt;br /&gt;+Proxy: [customers content]&lt;br /&gt;+Proxy: [contacts content]&lt;br /&gt;Итерация № 3&lt;br /&gt;...&lt;br /&gt;Далее, напряму с сервера&lt;br /&gt;Server[index content]&lt;br /&gt;Server[news content]&lt;br /&gt;Server[blog content]&lt;br /&gt;Server[customers content]&lt;br /&gt;Server[contacts content]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Из вывода ясно видно, что на первой итерации, при запросе всех пяти страниц, сервер участвует непосредственно при отдаче каждой из них. На второй и далее, сервер задействуется только для отдачи страниц обозначенных как динамические. И в завершении можно видеть, что благодаря единому интерфейсу, данные с сервера клиент может запрашивать напрямую. &lt;br /&gt;&lt;br /&gt;p.s. Картинку рисовал в Google Doc Drawing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-7191694092768863361?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/7191694092768863361/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=7191694092768863361' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/7191694092768863361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/7191694092768863361'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/04/proxy.html' title='Шаблон проектирования &quot;Заместитель&quot;(proxy).'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-968356000313632416</id><published>2010-04-21T12:57:00.000+03:00</published><updated>2010-04-21T13:10:12.750+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='extgwt'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>ExtGWT on GAE Trial-trip.</title><content type='html'>Целью проекта было желание протестировать хранилище(big table) Google Apps Engine. Ну что же, записную книжку или какую либо "домашнюю бухгалтерию" писать на нем уже можно. Нет, на самом деле на нем можно написать много чего, но так как всю свою ИТ-шную жизнь я так или иначе сталкиваюсь с программами для подсчета &lt;strike&gt;профита&lt;/strike&gt; чего-либо, то интересно было покрутить платформу именно в этом ключе. &lt;br /&gt;&lt;br /&gt;Итак, первые итоги. Впрочем в дальнейшем я пока не знаю что с этим со всем делать, так что возможно первые и последние. Всё приложение это одна табличка в хранилище, локально все работало великолепно, а в "облаках" же подкралась, ну не знаю, скажем так, неясность. При desc сортировке по id вылетало исключение на отсутствие индекса. Перерыв google до 10-й страницы, нашел, вроде на сайте поставщика JPA, как этот индекс создать. Создавался он на таблицу в 6 записей более 2(двух!) часов. Облака оказались очень неторопливыми. Впрочем, после того как индекс построился, ошибка никуда не делась. Я уже почти было плюнул на эту затею, но внезапно, там построился индекс по id desc, который по описанию полностью повторял мой в этой его части. То есть умная платформа сама достроила недостающий индекс и гордо отрапортовала в панели квот что три, из всего ста доступных, я уже использовал. Понять много это или мало все равно не получилось, так как мой индекс из двух полей(id asc, desc) все равно только "отожрал" квоту, а на ошибку не повлиял.&lt;br /&gt;&lt;br /&gt;Чем закончилось. Закончилось тем, что я по неосторожности сделал чек-аут пустого проекта из репозитория на свой и исходники почти аннигилировались. Впрочем, таких дураков как я Eclipse страхует и я смог восстановить сами исходные коды, но к сожалению структура проекта разрушилась и восстанавливать мне его уже лень, так как это муторно и особой надобности в этом нет. Кто хочет посмотреть, вот &lt;a href="http://okhmoddev.appspot.com/"&gt;адрес работающего приложения&lt;/a&gt;. Авторизация через службы Google Accounts, сразу предупреждаю что если будете что-то там создавать или редактировать, то я пишу e-mail в ту запись которую вы отредактировали. Ну так, на всякий.&lt;br /&gt;&lt;br /&gt;p.s. Google, ну добавьте пожалуйста в apps engine хотя бы sql-lite, пусть и дурацкий, но реляционный. И с прямыми запросами пожалуйста, без всех этих JDO, JPA и прочих &lt;strike&gt;развлечений&lt;/strike&gt; достижений инженеров Sun и Red Hat. И я буду ваш на веки!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-968356000313632416?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/968356000313632416/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=968356000313632416' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/968356000313632416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/968356000313632416'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/04/extgwt-on-gae-trial-trip.html' title='ExtGWT on GAE Trial-trip.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-6707269714844372639</id><published>2010-04-21T12:22:00.000+03:00</published><updated>2010-04-21T12:29:31.173+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='google wave'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='robot'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>Google Wave Robot.</title><content type='html'>В конце прошлого года мне прислали инвайт в Google Wave. После нескольких часов "чата" захотелось взглянуть на Wave API. Из двух существующих способов расширения волны: роботы и гаджеты, выбор пал в сторону роботов. Гаджеты представляют собой встраиваемые в сообщения(блипы в терминах Wave) блоки html/JavaScript и, не вдаваясь в детали, позволяют пользователям взаимодействовать с собой. Роботы, в свою очередь, являются полноценными приложениями на платформе Google Apps Engine и могут реагировать на события, такие как добавление в волну участника или новый блип. Так же, роботы могут создавать новые блипы, редактировать существующие, добавлять в волну адресатов(участников) и главное, использовать всю мощь облачных вычислений платформы Google Apps Engine. В свою очередь, в отличии от гаджетов, роботы ограничены в средствах визуализации, что впрочем не мешает создавать комбинированные расширения робот + гаджет. Более того, думаю именно эта связка способна превратить волну в платформу для решения огромного спектра задач. Иными словами, можно считать что робот отвечает за логику, а гаджет за представление. Однако в целом, это две самостоятельные сущности приложения Google Wave. &lt;br /&gt;&lt;br /&gt;Поскольку с первого взгляда волна больше всего напоминает коллективный чат, идея для робота пришла довольно быстро. Если кто не в курсе, в типичном веб-чате наряду с "роботами" заменяющими текстовые смайлы на графические, иногда существуют "роботы" реагирующие на заранее обозначенные слова или фильтрующие нецензурную лексику. Такого "цензора" я и решил написать. В принципе, задача довольно тривиальная: робот реагирует на каждый новый блип, читает его содержимое и если находит там вхождение или прямое соответствие, заменят подстроку - т.е. становится как бы соавтором сообщения, так как в волне можно совместно редактировать один и тот же блип. Этим роботы похожи на обычных участников. Кстати, сейчас их выдает наличие адреса в зоне @appspot.com, а когда появится возможность хостить их на собственных доменах и волновых серверах, не исключаю появления разнообразных роботов троллей, &lt;s&gt;SEO &lt;/s&gt;спаммеров и прочих продуктов эволюции интернета. &lt;br /&gt;&lt;br /&gt;Впрочем продолжим. GAE/GWT плагин для Eclipse IDE позволяет довольно легко создавать и публиковать приложения apps engine. Весь процесс описан в документах Google и не вызвал у меня никаких сложностей. Сложности начались в попытках разобраться с многочисленными "отказами в обслуживании" которые сыпались в консоль администратора, когда я начал тестировать робота. Робот то работал, то не работал и сходу было не так просто найти причины. Самое "веселье" заключалось в том, что пока я тестировал его самостоятельно, все вроде было ок. Однако, когда я создал публичную волну и попросил всех, кому это интересно помочь в тестировании, робот периодически умирал и не реагировал на сообщения. Вскоре, причины стали ясны. Честно говоря, я жутко не люблю "регулярные выражения". Каждый раз там, где  ими можно эффективно воспользоваться, я для начала пытаюсь обойтись без них. Так и здесь, решение обойтись без регулярок было выполнено в лучших индусских традициях: сообщение разбивается на "массив" слов, который в цикле перебирается. Каждое слово отправляется в функцию, в которой создается(!) массив слов подлежащих фильтрации и уже внутри цикла по нему мы сравниваем конкретные слова и вхождение подстрок. Собственно эти вложенные циклы и были причинами отказа в обслуживании. Реализация средствами регулярных выражений исправила ситуацию и робот заработал стабильно.&lt;br /&gt;&lt;br /&gt;Ну и в завершении. Во первых, доступ к волнам у меня совпал с периодом активного изучения Java. Таким образом робот оказался первым приложением которое исполнилось не на localhost, а в интернете, да еще и на период тестирования обрело своих пользователей. К сожалению, серия вандализма в публичных волнах, которая бушевала в конце прошлого года, докатилась и до нашей волны, в которой мы вместе с любезно согласившимися добровольцами тестировали робота. После этого, как мне показалось, интерес к волнам несколько спал, в том числе пропал интерес и к моему роботу. Однако он по прежнему доступен и работает по адресу &lt;i&gt;gwcensor@appspot.com&lt;/i&gt; , а исходный код можно посмотреть &lt;a href="http://code.google.com/p/robotcensor/"&gt;на google code&lt;/a&gt;. Сам сервис google wave оказался невероятно удобным для коллективного обсуждения проекта. Хотя, честно говоря, я кроме "мантиса" ничего и не видел. И последнее, если вы начинающий разработчик изучающий python или один из JVM зыков, я рискну порекомендовать в качестве небольшой практики разработать своего "питомца". В "волнах" уже есть некоторая аудитория и главное что подобный опыт позволяет немного окунуться в атмосферу реальных проектов, получить отклик пользователей и по случаю, познакомиться с возможностями Google Apps Engine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-6707269714844372639?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/6707269714844372639/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=6707269714844372639' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/6707269714844372639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/6707269714844372639'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/04/google-wave-robot.html' title='Google Wave Robot.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-6773992656172425092</id><published>2010-04-21T12:07:00.000+03:00</published><updated>2010-04-21T12:14:30.357+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reflection'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='rtti'/><title type='text'>Создание экземпляра класса через вызов закрытого конструктора средствами Java RTTI.</title><content type='html'>Подход, описанный в статье &lt;a href="http://habrahabr.ru/blogs/java/86381/"&gt;Final class одновременно в языке программирования Java?!&lt;/a&gt;, основан на отсутствии у класса открытых(public) конструкторов. Так же, там используется явный вызов исключения, которым автор страхует пользователя от вызова конструктора из методов самого UtilityClass класса. В статье сказано, что данное исключение, в целом, не обязательно. Однако, именно его наличие полностью гарантирует невозможность создания экземпляра UtilityClass. Ниже небольшой пример, демонстрирующий как создать экземпляр класса в отсутствии явного исключения в закрытом(private) конструкторе.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;lang&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;reflect&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Constructor&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;lang&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;reflect&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;InvocationTargetException&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; UtilityClass {&lt;br /&gt;&lt;br /&gt;  &lt;span style='color:#7f0055; font-weight:bold; '&gt;private&lt;/span&gt; UtilityClass() {&lt;br /&gt;    &lt;span style='color:#3f7f59; '&gt;//throw new AssertionError();&lt;/span&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; toString() {&lt;br /&gt;   &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;this&lt;/span&gt;.getClass().getName();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; RTTIPrivateConstructorCall {&lt;br /&gt;&lt;br /&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; main(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;[] args) {&lt;br /&gt;  &lt;span style='color:#7f0055; font-weight:bold; '&gt;try&lt;/span&gt; {&lt;br /&gt;&lt;br /&gt;   UtilityClass      instance;&lt;br /&gt;   &lt;span style='color:#7f0055; font-weight:bold; '&gt;Constructor&lt;/span&gt;&amp;lt;UtilityClass&gt;  privateConstructor =&lt;br /&gt;UtilityClass.class.getDeclaredConstructor();&lt;br /&gt;   privateConstructor.setAccessible(&lt;span style='color:#7f0055; font-weight:bold; '&gt;true&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;   instance = privateConstructor.newInstance();&lt;br /&gt;&lt;br /&gt;   &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"Hello from "&lt;/span&gt; + instance);&lt;br /&gt;&lt;br /&gt;  } &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;SecurityException&lt;/span&gt; e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  } &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;NoSuchMethodException&lt;/span&gt; e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  } &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;InvocationTargetException&lt;/span&gt; e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  } &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;IllegalAccessException&lt;/span&gt; e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  } &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;InstantiationException&lt;/span&gt; e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;Аналогичным образом Java Runtime Type Information прекрасно справляется с доступом к закрытым полям и методам. Довольно подробно аспекты работы этого механизма описаны в книге Брюса Эккеля "Философия Java".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-6773992656172425092?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/6773992656172425092/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=6773992656172425092' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/6773992656172425092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/6773992656172425092'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/04/java-rtti.html' title='Создание экземпляра класса через вызов закрытого конструктора средствами Java RTTI.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-4560690359920256761</id><published>2010-02-20T21:33:00.000+02:00</published><updated>2010-02-20T21:40:24.084+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='md5'/><title type='text'>Пример MD5 на Java, с использованием  MessageDigest.</title><content type='html'>Продолжаю причесывать исходники, которые могут быть полезны. В данном посте небольшой пример реализации сабжа. Надо сказать что в том же php, все делается в разы проще, но что поделать: иногда Java действительно очень разнообразна и многословна. Окончательное, вроде правильное решение нашлось по &lt;a href="http://www.spiration.co.uk/post/1199/Java%20md5%20example%20with%20MessageDigest"&gt;этой ссылке&lt;/a&gt;. В комментариях к тому посту разгорелся стандартный спор "физиков и лириков", как правильно, а как нет. Я, в свою очередь, ограничился сверкой результатов со штатной функцией MD5 СУБД MySql и на этом покамест решил успокоиться. Для шифрования паролей решения по ссылке вполне достаточно. Ниже, немного адаптированный для повседневного использования, код.&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;security&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;MessageDigest&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;security&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;NoSuchAlgorithmException&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; MD5 {&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; getHash(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt; str) {&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;MessageDigest&lt;/span&gt; md5 ;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;StringBuffer&lt;/span&gt;  hexString = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;StringBuffer&lt;/span&gt;();&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;try&lt;/span&gt; {&lt;br /&gt;                                    &lt;br /&gt;            md5 = &lt;span style='color:#7f0055; font-weight:bold; '&gt;MessageDigest&lt;/span&gt;.getInstance(&lt;span style='color:#2a00ff; '&gt;"md5"&lt;/span&gt;);&lt;br /&gt;            &lt;br /&gt;            md5.reset();&lt;br /&gt;            md5.update(str.getBytes()); &lt;br /&gt;                        &lt;br /&gt;                        &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;byte&lt;/span&gt; messageDigest[] = md5.digest();&lt;br /&gt;                        &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; i = 0; i &amp;lt; messageDigest.length; i++) {&lt;br /&gt;                hexString.append(&lt;span style='color:#7f0055; font-weight:bold; '&gt;Integer&lt;/span&gt;.toHexString(0xFF &amp;amp; messageDigest[i]));&lt;br /&gt;            }&lt;br /&gt;                                                                                        &lt;br /&gt;        } &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;NoSuchAlgorithmException&lt;/span&gt; e) {                        &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; e.toString();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;return&lt;/span&gt; hexString.toString();&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; main(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;[] args) {&lt;br /&gt;        &lt;br /&gt;        MD5 md5 = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; MD5();                                        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(md5.getHash(&lt;span style='color:#2a00ff; '&gt;"qwert123"&lt;/span&gt;));                        &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-4560690359920256761?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/4560690359920256761/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=4560690359920256761' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/4560690359920256761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/4560690359920256761'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/02/md5-java-messagedigest.html' title='Пример MD5 на Java, с использованием  MessageDigest.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-4825971500946613957</id><published>2010-02-20T18:12:00.000+02:00</published><updated>2010-02-20T18:46:32.068+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='пример'/><category scheme='http://www.blogger.com/atom/ns#' term='jdbc'/><title type='text'>Простейший пример подключения к БД MySql из Java.</title><content type='html'>&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Connection&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;DriverManager&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;PreparedStatement&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;ResultSet&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;sql&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;SQLException&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;import&lt;/span&gt;&lt;span style='color:#7f0055; '&gt; java&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;util&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;.&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;Properties&lt;/span&gt;&lt;span style='color:#7f0055; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;class&lt;/span&gt; SimpleDBConnection {&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#7f0055; font-weight:bold; '&gt;public&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;static&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;void&lt;/span&gt; main(&lt;span style='color:#7f0055; font-weight:bold; '&gt;String&lt;/span&gt;[] args) {&lt;br /&gt;    &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;Connection&lt;/span&gt;             conn  = &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;PreparedStatement&lt;/span&gt;   pstmt = &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;ResultSet&lt;/span&gt;            rs    = &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;try&lt;/span&gt; {&lt;br /&gt;                        &lt;br /&gt;             &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;Properties&lt;/span&gt; connInfo = &lt;span style='color:#7f0055; font-weight:bold; '&gt;new&lt;/span&gt; &lt;span style='color:#7f0055; font-weight:bold; '&gt;Properties&lt;/span&gt;();&lt;br /&gt;            &lt;br /&gt;            connInfo.put(&lt;span style='color:#2a00ff; '&gt;"characterEncoding"&lt;/span&gt;,&lt;span style='color:#2a00ff; '&gt;"UTF8"&lt;/span&gt;);&lt;br /&gt;            connInfo.put(&lt;span style='color:#2a00ff; '&gt;"user"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"username"&lt;/span&gt;);&lt;br /&gt;            connInfo.put(&lt;span style='color:#2a00ff; '&gt;"password"&lt;/span&gt;, &lt;span style='color:#2a00ff; '&gt;"pwd123"&lt;/span&gt;);&lt;br /&gt;            &lt;br /&gt;            conn  = &lt;span style='color:#7f0055; font-weight:bold; '&gt;DriverManager&lt;/span&gt;.getConnection(&lt;span style='color:#2a00ff; '&gt;"jdbc:mysql://localhost/?"&lt;/span&gt;, connInfo);&lt;br /&gt;            &lt;br /&gt;            pstmt = conn.prepareStatement(&lt;span style='color:#2a00ff; '&gt;"show databases;"&lt;/span&gt;);&lt;br /&gt;            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt;(pstmt.execute()) {&lt;br /&gt;                rs = pstmt.getResultSet();                                &lt;br /&gt;                &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;while&lt;/span&gt; (rs.next()) {&lt;br /&gt;                    &lt;span style='color:#3f7f59; '&gt;//System.out.println(rs.getString(1));&lt;/span&gt;&lt;br /&gt;                    &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(rs.getString(&lt;span style='color:#2a00ff; '&gt;"Database"&lt;/span&gt;));&lt;br /&gt;                }&lt;br /&gt;            }                                    &lt;br /&gt;        }&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;SQLException&lt;/span&gt; ex) {            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(ex.toString());&lt;br /&gt;            &lt;span style='color:#3f7f59; '&gt;//ex.printStackTrace();&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;        &lt;span style='color:#7f0055; font-weight:bold; '&gt;finally&lt;/span&gt; {&lt;br /&gt;            &lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;try&lt;/span&gt; {&lt;br /&gt;                &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (pstmt != &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;)&lt;br /&gt;                    pstmt.close();&lt;br /&gt;                &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;if&lt;/span&gt; (conn != &lt;span style='color:#7f0055; font-weight:bold; '&gt;null&lt;/span&gt;)&lt;br /&gt;                    conn.close();                &lt;br /&gt;            }&lt;br /&gt;            &lt;span style='color:#7f0055; font-weight:bold; '&gt;catch&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;SQLException&lt;/span&gt; ex) {            &lt;br /&gt;                &lt;span style='color:#7f0055; font-weight:bold; '&gt;System&lt;/span&gt;.out.println(&lt;span style='color:#2a00ff; '&gt;"On close: "&lt;/span&gt; + ex.toString());&lt;br /&gt;                &lt;span style='color:#3f7f59; '&gt;//ex.printStackTrace();&lt;/span&gt;&lt;br /&gt;            }                        &lt;br /&gt;            &lt;br /&gt;        }        &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Переменная connInfo содержит параметры подключения, в данном случае: кодировку, логин и пароль к БД. Переменная conn получает JDBC соединение c указанными параметрами. Конструкция conn.prepareStatement создает запрос и возвращает ссылку на него переменной pstmt, после исполнения запроса мы в переменную rs - получаем ResultSet(множество значений), который мы и пробегаем в цикле. &lt;br /&gt;&lt;br /&gt;В примере видно, что колонку можно получить как по ее порядковому номеру, начиная с единицы (закомментированная часть), так и по псевдониму запроса(select field as someName). Соответственно, если псевдоним не указан, то используется стандартное имя поля БД/колонки результата. В данном случае, приведенный выше пример выведет в консоль имена всех имеющиеся баз данных. Ну и в завершении, в блоке finally мы закрываем сначала Statement, который закроет все связанные с ним множества - ResultSet, а после и само соединение(conn).&lt;br /&gt;&lt;br /&gt;p.s. Для воспроизведения примера так же требуется подключить в classpath/к проекту Eclipse(Reference Libraries) mysql-connector-java*, который можно скачать с официального сайта MySQL AB или его зеркал.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-4825971500946613957?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/4825971500946613957/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=4825971500946613957' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/4825971500946613957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/4825971500946613957'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2010/02/mysql-java.html' title='Простейший пример подключения к БД MySql из Java.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-5361997027477117893</id><published>2009-10-09T14:23:00.000+03:00</published><updated>2010-02-21T22:54:32.652+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xpp'/><category scheme='http://www.blogger.com/atom/ns#' term='пятничная хрень'/><category scheme='http://www.blogger.com/atom/ns#' term='axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET C#'/><title type='text'>Что-то вроде Properties.</title><content type='html'>В свое время, читая про "свойства" в C#, придумался забавный трюк. Вкратце, суть свойств заключается в том, что при получении значения поля и при его установке, эти две операции можно наделить дополнительной логикой. Собственно трюк:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[xpp]:&lt;br /&gt;class PropertiesExample&lt;br /&gt;{&lt;br /&gt;    int     value;&lt;br /&gt;}&lt;br /&gt;int value(int   _value = value)&lt;br /&gt;{&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    if (PrmIsDefault(_value))&lt;br /&gt;        info("Get");&lt;br /&gt;    else&lt;br /&gt;        info("Set");&lt;br /&gt;&lt;br /&gt;    value = _value;&lt;br /&gt;&lt;br /&gt;    return value;&lt;br /&gt;}&lt;br /&gt;static void main(Args   _args)&lt;br /&gt;{&lt;br /&gt;    PropertiesExample   example = new PropertiesExample();&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;    info(strfmt("%1 ", example.value()));&lt;br /&gt;&lt;br /&gt;    info(strfmt("%1 ", example.value(100)));&lt;br /&gt;}&lt;br /&gt;[/xpp]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Впрочем, стоит упомянуть Джеффри Рихтера, чьи книги я пока не читал, но цитату запомнил:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"Лично мне свойства не нравятся, и я был бы рад, если бы их поддержку убрали из Microsoft .NET Framework и сопутствующих языков программирования. Причина в том, что свойства выглядят как поля, на самом деле являясь методами.".&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-5361997027477117893?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/5361997027477117893/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=5361997027477117893' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/5361997027477117893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/5361997027477117893'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2009/10/properties.html' title='Что-то вроде Properties.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-6378536066333924859</id><published>2009-10-02T16:45:00.000+03:00</published><updated>2009-10-05T14:25:52.594+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='мысли'/><category scheme='http://www.blogger.com/atom/ns#' term='xpp'/><category scheme='http://www.blogger.com/atom/ns#' term='пятничная хрень'/><category scheme='http://www.blogger.com/atom/ns#' term='axapta'/><title type='text'>Если бы были "замыкания"...</title><content type='html'>В х++ их конечно нет и вряд ли появится что-то подобное. Однако, на днях, читая обсуждение на тему setTmp(), подумалось, что в некотором случае они были бы удобны в аксапте. Например, что-то вроде:&lt;br /&gt;&lt;br /&gt;[xpp]:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;static void UnrealJob(Args _args)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    EmplTable    emplTable&lt;br /&gt;    {&lt;br /&gt;        Boolean validateWrite()&lt;br /&gt;        {&lt;br /&gt;            //Do nothing...&lt;br /&gt;            return true;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;    emplTable.setTmp();&lt;br /&gt;&lt;br /&gt;    emplTable.EmplId = "XAL";&lt;br /&gt;&lt;br /&gt;    emplTable.insert();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ну и для классов тоже, а еще вдогонку и для интерфейсов =))&lt;br /&gt;&lt;br /&gt;[java]:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;interface IClosureTest {&lt;br /&gt; &lt;br /&gt; public void runIt();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class ForBlog {&lt;br /&gt; &lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  &lt;br /&gt;  IClosureTest test = new IClosureTest() {&lt;br /&gt;   public void runIt() {&lt;br /&gt;    System.out.println("runIt method!!!");&lt;br /&gt;   }&lt;br /&gt;  };&lt;br /&gt;  &lt;br /&gt;  test.runIt(); //Console: runIt method!!!    &lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;p.s. В C#, на сколько я помню, все еще веселей.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-6378536066333924859?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/6378536066333924859/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=6378536066333924859' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/6378536066333924859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/6378536066333924859'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2009/10/blog-post.html' title='Если бы были &quot;замыкания&quot;...'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-7310633303069976739</id><published>2009-01-12T11:45:00.000+02:00</published><updated>2010-02-21T22:53:59.324+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='QueryRun'/><title type='text'>Join между временной и постоянной таблицей через QueryRun.</title><content type='html'>Однажды, отлаживая нетривиальный код, наткнулся на subj. Не зная про эту «фичу»,  я долго удивлялся почему запрос возвращает такой странный набор данных!?! Ниже приведен простенький Job-ик, который демонстрирует  существование этой возможности в DAX. В иерархии запроса временная таблица должна быть первым источником данных.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[xpp]&lt;br /&gt;static void JoinTmpTablesOnQuery(Args _args)&lt;br /&gt;{&lt;br /&gt;    LedgerTrans             ledgerTrans;&lt;br /&gt;    LedgerTable             ledgerTableTmp;&lt;br /&gt;&lt;br /&gt;    int                     i;&lt;br /&gt;    int                     transCnt   = 20;&lt;br /&gt;&lt;br /&gt;    Query                   query      = new Query();&lt;br /&gt;    &lt;br /&gt;    QueryBuildDataSource    qbdsTable  = query.addDataSource(tableNum(LedgerTable));&lt;br /&gt;    QueryBuildDataSource    qbds2Trans = qbdsTable.addDataSource(tableNum(LedgerTrans));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    QueryRun                queryRun;&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;    qbds2Trans.relations(true);&lt;br /&gt;&lt;br /&gt;    ledgerTableTmp.setTmp();&lt;br /&gt;    &lt;br /&gt;    ledgerTableTmp.data(LedgerTable::find("02.010"));&lt;br /&gt;    ledgerTableTmp.insert();&lt;br /&gt;    &lt;br /&gt;    ledgerTableTmp.data(LedgerTable::find("01.030"));&lt;br /&gt;    ledgerTableTmp.insert();&lt;br /&gt;    &lt;br /&gt;    queryRun = new QueryRun(query);&lt;br /&gt;&lt;br /&gt;    queryRun.setCursor(ledgerTableTmp, 1);&lt;br /&gt;    &lt;br /&gt;    i = 0;&lt;br /&gt;&lt;br /&gt;    while (queryRun.next())&lt;br /&gt;    {&lt;br /&gt;        ledgerTableTmp = queryRun.getNo(1);&lt;br /&gt;        ledgerTrans    = queryRun.getNo(2);&lt;br /&gt;&lt;br /&gt;        info(strfmt("AccountNum %1 , AmountCur %2 , (tmpRecId %3 , regRecId %4)",&lt;br /&gt;                     ledgerTableTmp.AccountNum,&lt;br /&gt;                     ledgerTrans.AmountCur,&lt;br /&gt;                     ledgerTableTmp.RecId,&lt;br /&gt;                     ledgerTrans.RecId));&lt;br /&gt; &lt;br /&gt;        i++;&lt;br /&gt;        &lt;br /&gt;        if (transCnt &amp;&amp; i == transCnt)&lt;br /&gt;            break;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;[/xpp]&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-7310633303069976739?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/7310633303069976739/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=7310633303069976739' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/7310633303069976739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/7310633303069976739'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2009/01/join-queryrun.html' title='Join между временной и постоянной таблицей через QueryRun.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-1232993346279671005</id><published>2008-09-30T18:34:00.000+03:00</published><updated>2010-02-21T22:55:23.042+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Должностные лица'/><category scheme='http://www.blogger.com/atom/ns#' term='axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='Локализация'/><title type='text'>Модификация формы "Должностные лица".</title><content type='html'>&lt;b&gt;Введение.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;В Российской локализации Dynamics Ax существует специальный модуль хранящий историю ФИО и должностей лиц, которые должны подписывать те или иные документы. Основания форма настроек располагается по пути Основное/Настройка/Контакты/Должностные лица. На вкладках этой формы находятся настройки относящиеся к различным документам системы, сгруппированные по модулям. Выбрав модуль и нужный документ, мы можем указать настройки по умолчанию, которые в последствии попадут в печатную форму соответствующего документа. Одна из особенностей заключается в том, что в момент печати, например счета-фактуры, данные о должностях подписывающих документ берутся не из этих настроек. В печатную форму попадают данные, сохраненные в специальной таблице, что дает возможность печатать любой документ с теми ФИО, которые были в настройках(т.е. работали в компании) на момент создания документа(накладной, фактуры, складских документов итп). Иными словами, во время разноски система смотрит настройку того или иного документа и копирует от туда данные в специальную таблицу. Позже данные этой таблицы используются при выводе печатной формы. Другой особенностью является то, что для конкретного документа можно ввести только определенный набор и кол-во позиций,  потому что в конечном счете в печатной форме отведено определенное место для подписей должностей. Таким образом, кроме собственно позиций, ФИО и должностей, настройке больше ничего не подлежит. Любое изменение или дополнение можно сделать только путем изменения самой отчетной формы, а так же алгоритмов разноски, печати и настройки должностных лиц.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Общая логика работы формы.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Условно говоря, логику работы с формой можно разделить на три типа: &lt;br /&gt;&lt;br /&gt;1.В самом простом случае мы заполняем три поля: "Позиция", "Наименование"(Имя сотрудника) и "Обращение"(Должность сотрудника). Такой набор полей используется для закладок: "Разное", "Главная книга" и "Запасы". &lt;br /&gt;&lt;br /&gt;2.Для закладок "Заказы на продажу" и "Заказы на покупку" добавляются три поля: "Код связи", "Код связи контрагента" и информативное "Свой?". В случае, если мы устанавливаем в поле "Код связи" значение "Запись", в зависимости от модуля у нас появляется возможность выбрать контрагента в поле "Код связи контрагента", при этом в зависимости от значения поля "Позиция" меняет свое значение флаг "Свой?". В случае, если сотрудник "свой", то поле "Наименование" заполняется из справочника Сотрудников(Основное/сотрудник.), иначе из справочника "Контактные лица"(Основное/Настройка/Контакты/Контактное лицо).&lt;br /&gt;&lt;br /&gt;Пример: допустим для модуля "Заказы на покупку" документа "Накладная" в настройках есть строка с кодом контрагент "Поставщик1" и позицией "Отпустил".В этом случае выпадающий список покажет все контактные лица, связанные с поставщиком: "Поставщик1". В свою очередь, если это внутренняя позиция компании - "Принял", то выпадающий список будет содержать справочник сотрудников.&lt;br /&gt;&lt;br /&gt;3. Для закладки "Учет МЦ", помимо новых полей описанных в пункте 2, добавляются поля "Связь со складом" и "Склад". Эта настройка актуальная для позиций "Принял" и "Отпустил". Мы можем указать эти позиции с введенными в систему складами. Далее, указав в строке закупки определенный склад, в диалоге обработки "Отборочной накладной" по "Заказу на покупку" система в позиции принял и отпустил подтянет соответствующие ФИО.  (В дальнейшем эти данные будут использоваться при печати документов Приходный ордер/Акт о приемке). Хотелось бы добавить, что я не до конца понял, как ведет себя данная настройка, в том случае, если в строках закупки есть несколько складов. Сложилось впечатление, что несмотря на то, что в информацию о текущих должностных лицах попадают все настроенные "Принял"/"Отпустил" в соответствии с набором складов в строках, при печати, например "Приходного ордера" система подтягивает первую найденную "Пару". &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Добавление новой позиции.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Для простоты, рассмотрим пример добавления новой позиции на закладку "Разное" формы "Должностные лица". В стандарте эта закладка содержит всего две настройки: "Руководитель" и "Главбух", которые используются в большинстве печатных форм проведенных документов. Добавим, для примера, позицию "Заместитель руководителя". Имя я выбрал специально длинным и исчерпывающим, но на этом примере позже будет раскрыта одна особенность добавления новой позиции, с которой довелось столкнуться. &lt;br /&gt;&lt;br /&gt;Первым делом нам нужно добавить новый элемент AssistantDirector с меткой "Заместитель руководителя" в перечисление(Enum) OffPosition_RU. Далее, в классе OfficialsPositionLookupEngine_RU, в методе initPositions добавим для закладки разное(OffReportType_RU::General) инициализацию нашей позиции.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;Код:&lt;br /&gt;---&lt;br /&gt;case OffReportType_RU::General                  :&lt;br /&gt;            add(OffPosition_RU::Director);&lt;br /&gt;            add(OffPosition_RU::Accountant);&lt;br /&gt;            //OZKA, 30.08.2008 --&gt;&lt;br /&gt;            add(OffPosition_RU::AssistantDirector);&lt;br /&gt;            // &lt;--&lt;br /&gt;            break;&lt;br /&gt;---&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Теперь, если мы откроем форму и создадим новую строку, в выпадающем списке поля позиция появится "Заместитель руководителя", однако после таких элементарных действий выбрать её мы пока не можем. Найдем EDT OffPositionStr_RU и изменим его длину на 30 символов. Затем, снова откроем форму и теперь видим, что у нас появилась возможность выбрать наше "длинное и исчерпывающее" название новой позиции. Впрочем, система и после этого сообщит, что "В отчете "Общие" отсутствует поле "Заместитель руководителя". Найдем в АОТ класс OffCheckPosition_RU и подправим его метод checkGeneral&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;Код:&lt;br /&gt;---&lt;br /&gt;private boolean checkGeneral()&lt;br /&gt;{&lt;br /&gt;    boolean ok;&lt;br /&gt;&lt;br /&gt;    switch (position)&lt;br /&gt;    {&lt;br /&gt;        case OffPosition_RU::Director,&lt;br /&gt;             OffPosition_RU::Accountant,&lt;br /&gt;             //OZKA, 30.08.2008 --&gt;&lt;br /&gt;             OffPosition_RU::AssistantDirector :&lt;br /&gt;             // &lt;--&lt;br /&gt;            ok = true;&lt;br /&gt;            break;&lt;br /&gt;&lt;br /&gt;        default :&lt;br /&gt;            ok = false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return ok;&lt;br /&gt;}&lt;br /&gt;---&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;После этого, у нас, наконец, появилась возможность указать на закладке разное новую позицию. Далее, логично для "внутренней" позиции ограничить выбор имен справочником сотрудников. Для этого в таблице OfficialsTable_RU изменим метод isOurGuy.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;Код:&lt;br /&gt;---&lt;br /&gt;case OffReportType_RU::General                   :&lt;br /&gt;            ret = (this.Position == OffPosition_RU::Director) ||&lt;br /&gt;                  (this.Position == OffPosition_RU::Accountant)&lt;br /&gt;                  //OZKA, 30.08.2008 --&gt;&lt;br /&gt;                  || (this.Position == OffPosition_RU::AssistantDirector)&lt;br /&gt;                  // &lt;--&lt;br /&gt;                  ;&lt;br /&gt;            break;&lt;br /&gt;---&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Теперь выпадающий список для нашей новой позиции соответствует спискам полей "Руководитель" и "Главбух", то есть формируется на основе таблицы EmplTable.&lt;br /&gt;&lt;br /&gt;Остается поддержать нашу новую позицию при разноске, например, накладной по "Заказу на продажу". За создание проводок в таблице  OfficialsTrans_RU отвечает класс OfficialsServ_RU. Добавим в его метод initSalesInvoice следующие строки:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;Код:&lt;br /&gt;---&lt;br /&gt;//OZKA, 30.08.2008 --&gt;&lt;br /&gt;    this.insertOrUpdate(OffPosition_RU::AssistantDirector,&lt;br /&gt;                        OffReportType_RU::General,&lt;br /&gt;                        "",&lt;br /&gt;                        OffTableAll_RU::All,&lt;br /&gt;                        true,&lt;br /&gt;                        OffReportType_RU::SalesInvoice,&lt;br /&gt;                        true,&lt;br /&gt;                        false);&lt;br /&gt;    &lt;br /&gt;    // &lt;--&lt;br /&gt;---&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Теперь, при разноски накладной по заказу, в таблицу OfficialsTrans_RU будет попадать информация, в том числе, и о нашей новой позиции. Если мы вызовем форму обработки накладной, то на соответствующей закладке мы сможем увидеть нашу настройку. Не вдаваясь в подробности, как устроена печать накладной по заказу, в общем случае добраться до какой либо позиции можно с помощью метода find таблицы OfficialsTrans_RU. А сама "сессия" должностных лиц хранится в поле OffSessionId_RU таблицы CustInvoiceJour или других таблицах документов, поддерживающих модуль "Должностные лица". По аналогии можно изменять поведение и набор позиций для других вкладок (модулей) системы и доступных для них настроек должностей печатных форм.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Summary.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;В качестве итога скажу, что не стал писать о добавлении новой закладки на форму "Должностные лица", допустим для реализации поддержки собственного модуля или решения. Так же, кое-что о модуле можно прочитать скачав вложение темы - &lt;a href = "http://axforum.info/forums/showthread.php?t=13785"&gt;Российские складские отчеты&lt;/a&gt;. Там на примере того, как создавать новый отчет по складским журналам, в том числе, рассказывается как поддержать модуль должностные лица, для своего складского отчета. &lt;br /&gt;&lt;br /&gt;p.s. Если я что-то упустил или сильно напутал, замечания приветствуются =))&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-1232993346279671005?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/1232993346279671005/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=1232993346279671005' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/1232993346279671005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/1232993346279671005'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2008/09/blog-post.html' title='Модификация формы &quot;Должностные лица&quot;.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-1717530631768926846</id><published>2008-08-27T10:44:00.000+03:00</published><updated>2010-02-21T22:56:17.514+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='Отчеты'/><title type='text'>Многоколоночные отчеты средствами Dynamics AX.</title><content type='html'>За время работы с Аксаптой мне неоднократно приходилось создавать отчеты, "растущие в ширину", штатными средствами системы DAX 3.0. После того, как я впервые, изрядно намучавшись с управлением дизайном отчета в "рантайм", очень хотелось все это упорядочить. Однако, поскольку подобные задачи на проектах возникали в разное время, собрать относительно универсальный набор классов не получалось. В Российской локализации уже имеется подобный фреймворк RLedgerSheet*, но для некоторых отчетов, это как "из пушки по воробьям", не говоря о том, что доскональное изучение этого "монстра" заняло бы очень много времени.&lt;br /&gt;&lt;br /&gt;В конце поста, можно скачать простенький движок, который удалось написать. Все что требуется программисту, что бы им воспользоваться, это собрать структуру(Map) с контейнером в ключе и значении. Так же, нужно создать заголовки для колонок ключа и значений(два контейнера). Вложенные контейнеры естественно не допускаются. Кол-во заголовков и значений должно совпадать.&lt;br /&gt;&lt;br /&gt;По сути, вся работа сводится к тому, что бы создать наследника от класса SimpleSheetEngineData и реализовав метод fillReportDataMap(), заполнить соответствующую структуру(reportDataMap) требуемыми данными. Так же указать названия колонок(методы keyHeader(), valueHeader()) и запустить класс на исполнение. В проекте имеется демо-реализация(ExampleDataObject), наглядно иллюстрирующая простоту данного движка.&lt;br /&gt;&lt;br /&gt;Тестировалось на DAX 3.0 SP3. thx за Bug Report!&lt;br /&gt;&lt;br /&gt;&lt;strike&gt;SimpleSheetEngine_OZKA.rar&lt;br /&gt;&lt;/strike&gt;&lt;br /&gt;&lt;br /&gt;upd: Правильная ссылка(в предыдущей выпал пункт меню) &lt;a href="http://narod.ru/disk/2255989000/SimpleSheetEngine_OZKA%20(copy%202).rar.html"&gt;SimpleSheetEngine_OZKA (copy 2).rar&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-1717530631768926846?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/1717530631768926846/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=1717530631768926846' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/1717530631768926846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/1717530631768926846'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2008/08/dynamics-ax.html' title='Многоколоночные отчеты средствами Dynamics AX.'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1958886800716997908.post-1859514343470741565</id><published>2008-03-27T12:29:00.000+02:00</published><updated>2010-02-21T22:56:33.309+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='axapta'/><title type='text'>Hello World</title><content type='html'>Давно думал над идеей создания сайта посвященного разработке в системе MS Dynamics Ax. Учитывая, что контента не так много, попробую его потихоньку доводить до ума и публиковать тут.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1958886800716997908-1859514343470741565?l=ozka-lemming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ozka-lemming.blogspot.com/feeds/1859514343470741565/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1958886800716997908&amp;postID=1859514343470741565' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/1859514343470741565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1958886800716997908/posts/default/1859514343470741565'/><link rel='alternate' type='text/html' href='http://ozka-lemming.blogspot.com/2008/03/hello-world.html' title='Hello World'/><author><name>OZKA</name><uri>http://www.blogger.com/profile/02253067720162200131</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://4.bp.blogspot.com/_PFXVy78GiZk/TIj0V8Gm9mI/AAAAAAAAA98/LfVtSvgXnGY/S220/and+me.jpg'/></author><thr:total>0</thr:total></entry></feed>
