21 Октябрь 2009

Своё - родное. Кирилица в java

Вступление...
Хотелось ли вам когда нибудь изобрести свой язык программирования, который бы позволял всё писать на кирилице и идентификаторы, и названия процедур-функций, и команды. Что то вроде:

Цикл ( целый И = 0 ; И < КоличествоДвигателей ; И++ )
Если (НеобходмаяМощность[И] < ДоступныйРесурс[И] ) Тогда
выделитьЕщёРесурсов(НеобходмаяМощность);
И--;
Иначе
запуститьПроцессПереработки();
Конец Если;
Конец Цикл;

Скажете бред. Вовсе нет, среди множества русскоговорящих программистов около 60% владеют английским языком на уровне pre-intermediate(ниже среднего) или еще ниже. Так что код, в котором все слова были бы интуитивно понятны вероятно для них был бы роднее. Так считаю не только я.
В любимом всеми читателями этого бложка язык программирования JAVA также сделал первый шаги в эту сторону. Нет, выше приведенный сегмент кода не будет работать, он даже не скомпилируется.
Продолжение...
Но вот следующий пример красочно демонстрирует лояльность java к кирилице, и совсем уж не ясно почему на просторах интернетов столько тем с комбинациями с трёх слов: java+кирилица+проблемы.


public class Гражданин {
private String Фамилия;
private String Имя;
private String Отчество;
private String Родина;
private int Возраст;
private boolean Беспартийный;
private boolean Судимый;

public String getФамилия() {
return Фамилия;
}
public void setФамилия(String фамилия) {
Фамилия = фамилия;
}
public String getИмя() {
return Имя;
}
public void setИмя(String имя) {
Имя = имя;
}
public String getОтчество() {
return Отчество;
}
public void setОтчество(String отчество) {
Отчество = отчество;
}
public String getРодина() {
return Родина;
}
public void setРодина(String родина) {
Родина = родина;
}
public boolean isБеспартийный() {
return Беспартийный;
}
public void setБеспартийный(boolean беспартийный) {
Беспартийный = беспартийный;
}

public boolean isСудимый() {
return Судимый;
}
public void setСудимый(boolean судимый) {
Судимый = судимый;
}
public void setВозраст(int возраст) {
Возраст = возраст;
}
public String toString(){
return
(Беспартийный?"Беспартийный":"Партийный")+" гражданин "+
Фамилия+" "+Имя+" "+Отчество+
" проживающий в "+Родина+
" "+Возраст+" лет отроду"
+(Судимый?" имеет судимости":" судимостей не имеет");
}

public static void Распечатать(Object подозреваемыйОбъект){
System.out.println(подозреваемыйОбъект);
}

public static void main(String []строчка){
Гражданин петров = new Гражданин();
петров.setФамилия("Иванов");
петров.setИмя("Иполит");
петров.setОтчество("Васильевич");
петров.setРодина("КНДР");
петров.setВозраст(45);
петров.setБеспартийный(false);
петров.setБеспартийный(false);
Распечатать(петров);

}

}


И получаем следующий вывод:

d:\projects\eclipse\Test\bin>java Гражданин
Партийный гражданин Иванов Иполит Васильевич проживающий в КНДР 45 лет отроду судимостей не имеет


Как показывает пример - идентификаторы, параметры, названия методов, и даже названия классов могут состоять из кирилических символов. Единственное что остаётся для меня пока тайной - в какой версии была введена такая возможность, существовала ли она всегда. Десяти минутное насилование googla не дало ответ на этот вопрос.

P.S.: необходимо заметить что практическое применения второго примера (комбинация английских и русских слов в коде) довольно низкая, из за постоянного переключения раскладок и соответственно низкой скорости набора.

10 Май 2009

[Oracle PL/SQL] Преобразование строки в маcсив

Несколько дней назад перед мною стала интересная задача : необходимо список сокращений, представленных в виде строки через запятую, преобразовать в массив.
На ум сразу приходит самое простое но не очень эстетическое решение - написать Pl/Sql процедуру, которая будет выполнять такую задачу.


SQL> CREATE OR REPLACE FUNCTION convert_comma_to_table(p_list IN VARCHAR2)
2 RETURN test_type
3 AS
4 l_string VARCHAR2(32767) := p_list || ',';
5 l_comma_index PLS_INTEGER;
6 l_index PLS_INTEGER := 1;
7 l_tab test_type := test_type();
8 BEGIN
9 LOOP
10 l_comma_index := INSTR(l_string, ',', l_index);
11 EXIT WHEN l_comma_index = 0;
12 l_tab.EXTEND;
13 l_tab(l_tab.COUNT) := SUBSTR(l_string, l_index, l_comma_index - l_index);
14 l_index := l_comma_index + 1;
15 END LOOP;
16 RETURN l_tab;
17 END f_convert;
18 /
Довольно простая функция, которая успешно выполнит поставленную задачу.
Потратив некоторое время на поиски , я натолкнулся на вариант покрасивее. В системном пакете dbms_utility есть функция comma_to_table , которая выполняет аналогичную функциональность. Пример использования :
SQL> DECLARE
2 l_tab dbms_utility.uncl_array;
3 l_tablen number;
4 BEGIN
5 dbms_utility.comma_to_table('A,B,C', l_tablen, l_tab);
6 dbms_output.put_line('TABLE LENGTH : '|| l_tablen);
7 dbms_output.put_line('TABLE COUNT : '|| l_tab.COUNT);
8 for i in 1..l_tablen
9 loop
10 dbms_output.put_line(l_tab(i));
11 end loop;
12 END;
13 /
Замечание! На самом деле эта процедура используется для внутренних целей Oracle, поэтому имеется ряд требований к элементам будущего массива:
- это не должны быть числа, в т.ч. слова начинающиеся на цифры;
- это не должны быть зарезервированные слова;
- это не должны быть строки длиннее 30 символов.
Первые два условия я обошёл добавляя перед каждой запятой спец строку, а после преобразования удаляя её, так что в итоге удалось воспользоватся этой удобной поцедуркой из dbms_utility.

Судьба блога 2009

Уже почти год как я поменял специализацию - теперь я программирую на PL/SQL под Oracle. Так что тематика статей далее тоже немного изменится. Это не значит что я перестану писать о Java. Нет. Кровь Java девелопера всё ещё течёт в моих жилах, так что я продолжу развиватся в этом направлении. Но обстоятельства таковы, что я на данный момент прокачиваюсь в области Oracle и готов делится кое какими своими наработками.

Спасибо за внимание. Читайте с удовольствием.

05 Декабрь 2008

Java FX 1.0 релиз состоялся

Вчера, 04.12.2008, состоялся релиз Java FX 1.0. Посмотреть примеры работы, изучить туториалы и скачать SDK можно с сайта http://www.javafx.com/

Sun's JavaFX 1.0 platform opens a vast global market for developers and content authors who want to deploy their content, services and experiences across all the screens of their customers' lives. Worldwide industry estimates show that Java technology is already on more than 90 percent of desktops and laptops, 85 percent of mobile devices and is a technology leader in next-generation televisions, Blu-ray disc players and TV set-top boxes.

Множественные уязвимости в Sun Java JDK и JRE

Обнаруженные уязвимости позволяют удаленному пользователю обойти некоторые ограничения безопасности, получить доступ к важным данным, вызвать отказ в обслуживании и скомпрометировать целевую систему.
Всего 23 уязвимости(SecurityLab)

Решение: Установите исправление

JDK and JRE 6 Update 11:
http://java.sun.com/javase/downloads/index.jsp
JDK and JRE 5.0 Update 17:
http://java.sun.com/javase/downloads/index_jdk5.jsp
SDK and JRE 1.4.2_19:
http://java.sun.com/j2se/1.4.2/download.html
SDK and JRE 1.3.1_24:
http://java.sun.com/j2se/1.3/download.html

Источники:

Sun News Radio

Узнать новости Sun Microsystems можно из первых уст http://www.blogtalkradio.com/stations/sunradio/SunNews

28 Ноябрь 2008

Работа со строками в oracle

Наиболее частая операция, которую необходимо выполнять - это выбор подстроки из строки. Для этого в oracle присутствует специальная встроенная функция substr
например : substr('test string #1', 5, 11 ) , где 1й параметр - это задана строка, 2й - позиция с которой начинается подстрока, 3й(не обязательный) - длинна подстроки.
Если точна позиция начала подстроки не известна , можно воспользоваться функцией instr
Например instr('test string #1', ' ' ) - будет найдено первое вхождение пробела в строку. В функции instr есть ещё третий параметр, который задаёт начало поиска, причём если указать -1 начало будет производится с конца строки.

Другие полезные функции:

ascii('S') - ascii код символа
upper / lower / initcap - преобразования регистра букв в большие / маленькие / первая большая все остальные маленькие.
chr(168) - получения символа по заданному ascii коду
concat('s1','s2') - соединение строк
trim / rtrim / ltrim - отбрасывание пробелов
reverse('12345') - получение строки с символами в обратном порядке
length - длинна строки

23 Ноябрь 2008

Паттерн поведения Observer (наблюдатель)

Наблюдатель (Observer) - паттерн поведения объектов, устанавливающий систему оповещения объектами своих соседей в процессе их деятельности.
Известен также под именами: Dependents (подчиненные), Publish-Subscribe (издатель-подписчик).

В процессе функционирования и взаимодействия объектов системы нужно оповещать других участников по завершении какой-нибудь значимой операции. Конечно же, можно в каждый такой класс, производящий значимые действия добавлять обращение к этим всем другим заинтересованным объектам, но таким образом мы дублируем связи между объектами (система становится все менее и менее гибкой) – это еще и в разы затруднит последующую модификацию каких либо участников, т.к. необходимо будет перекомпилировать этот код обращения ко всем заинтересованных субъектам.
В этом случае очень подошло бы иметь такую структуру, в которой каждый участник, если он заинтересован в каких-либо событиях системы, мог бы самостоятельно «подписаться» на эти изменния независимо от других заинтересованных участникам – и, таким образом, получая уведомления об этих событиях – выполнять требуемые ответные действия.
В результате – не создается лишних связей: есть источник значимых действий, есть заинтересованные в фактах выполнения этих действий субъекты, никак не связанный друг с другом, количество которых при этом – также неограниченно.

Паттерн-наблюдатель описывает именно такой подход: определяет зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом и автоматически обновляются.

Реализация паттерна поведения Наблюдатель (Observer).

/** Observer design pattern sample
*/

import java.util.ArrayList;
import java.util.List;

public class Child {
// --
List list = new ArrayList();
void addObserver(Observer o){
list.add(o);
}
void removeObserver(Observer o){
list.remove(o);
}
void notifyObservers(){
for (Observer o:list){
o.update();
}
}
// --
void childGrow(int newAge){
System.out.println("Age of child changed to " + newAge);
notifyObservers();
}
public static void main(String []s){
Child ot = new Child();
ot.childGrow(1);
ot.addObserver(new Food());
ot.addObserver(new Toys());
ot.addObserver(new Clothes());
ot.childGrow(3);
ot.removeObserver(new Food());
ot.childGrow(10);
ot.removeObserver(new Toys());
ot.childGrow(15);
ot.addObserver(new Food());
ot.childGrow(20);
ot.removeObserver(new Food());
ot.removeObserver(new Clothes());
ot.childGrow(25);
}
}

interface Observer {
void update();
}

abstract class BaseObserver implements Observer {
public boolean equals(Object obj) {
return this.getClass().equals(obj.getClass());
}
}

class Clothes extends BaseObserver {
public void update() {
System.out.println("Change childs' clothes");
}
}

class Toys extends BaseObserver {
public void update() {
System.out.println("Change childs' toys");
}
}

class Food extends BaseObserver {
public void update() {
System.out.println("Change childs' food");
}
}


Итак, у нас есть класс Child , который описывает модель ребёнка, основное действие - ребёнок растёт : childGrow, и в зависимости от возвраста ребёнка необходимо менять одежду, еду, игрушки - эти сущности описываются классами Clothes, Food, Toys соответственно. Эти три сущности реалиузют интерфейс Observer через класс BaseObserver.
После создания экземпляра класса ребёнка мы можем добавить или удалить специфических наблюдателей, и при достижении ребёнком какого то возраста (вызов childGrow) автоматически произойдёт обновление зарегистрированных в это время слушателей.


Источники:
Ппаттерн наблюдатель
Observer pattern
Speaking on the Observer pattern

22 Ноябрь 2008

Перенаправление системного вывода в файл

Для того что бы выводить информацию из Java программы в файл не обязательно использовать навороченные системы логгирования.
Можно просто перенаправить стандартный поток вывода и стандартный поток для ошибок в файл.
Сделать это можно с помощью следующего фрагмента кода:


PrintStream st = new PrintStream(new FileOutputStream("output.txt"));
System.setErr(st);
System.setOut(st);

20 Ноябрь 2008

Java EE справочник по русски

Java 2 Enterprise Eddition (J2EE)

Обзор J2EE:
Учебник по J2EE (PDF):
Разработчикам: