четверг, 3 апреля 2008 г.

Java compiler лажает

Запустите следующую программу:
public class BooleanTest {
public static void main(String[] arg) {
System.out.println(1 == 2 ? false : null);
}
}

Скомпилировали? Словили NullPointerException?
С какого рожна компилятор решил, что null может быть приведён к типу Boolean? Чтобы запустить auto-unboxing? Это всё зло!

вторник, 1 апреля 2008 г.

Те Ещё Дни

Завтра начинаются SunTechDays в Питере. Я там вечером буду, с пяти и до упора. В четверг и тяпницу - не поеду. Лениво. Надо ведь ещё и в пятничный преф поиграть ;)
Регистрация закрыта, так как мест больше нет. Но в связи с бешеным спросом наши организаторы попытаются выделить ещё несколько мест для тех, кто не успел зарегистрироваться. Я за Рустика замолвил словечко, может и ему входной билет достанется. А вечером я планирую попить пивка У Рудольфа вместе с моим коллегой из Москвы. Вместе работали в Люксофте.
Я, как и прошлый раз, буду стоять на будке JavaSE. Постараюсь выложить демки на JavaFX, надо которыми сейчас работаю. Хотя на сегодняшний момент это ещё очень глючная вещь. Я в пятницу оставил демку с летающими буквами, а в понедельник обнаружил, что программа упала, а система показала сообщение о том, что память кончилась и ей поплохело. Пришлось завести баг...

понедельник, 31 марта 2008 г.

Соседи

У нас на этаже - 5 квартир. Мы с краю, а бижайшие к нам соседи - странные люди. С некоторого момента тётка с нами вообще не разговаривает. Почему - не знаю. Невоспитанная, видимо. Вот сегодняшний пример...
Выходим с утра с Мишкой, а Юля пока одевается в квартире. Ну Мишка уже к лифту подходит, а я пока дверь закрываю. Тут соседке приспичило и она решила выйти, а так как дверь её квартиры открывается наружу, то она её попала по мне. Я с ней, как это полагается, поздоровался, а она даже не извинилась. Я пошёл к Мишке. Стоим у лифта, ждём Юлю. Выходит эта тётка в халате и общую железную дверь на распашку оставляет. К соседям, видимо, собралась. Мишка (сам, причём) решает, что дверь надо закрыть, и захлопывает её. Тётка тут напряглась, видимо, и позвонила к себе в квартиру (в звонок). Вглядывает её сын и она кричит ему, чтобы он открыл дверь. Ну он дёрнул было замок, а дверь-то открыта. Ну он её приоткрыл и в непонятках ушёл в квартиру. А тётка поехала на лифте к соседям.
Я не знаю, что она хотела этим сказать мне, но если бы она не вернулась раньше, чем Юля вышла, то я бы всё равно закрыл дверь на ключ. И ей пришлось бы опять звонить сыну, вытаскивать его в общий тамбур, чтобы дверь открыть. Не в моих правилах дверь нараспашку открытой держать.
Остальные соседи более-менее нормальные люди. Даже сын этой тётки. По крайней мере он здоровается при встрече. А она от нас вызывающе так нос воротит. Почему - не знаю. И такие соседские отношения немного напрягают Юлю. Мне то что! Я пуленепробиваемый. Я на эту тётку давно положил 8===Э

пятница, 28 марта 2008 г.

Java Puzzle 80: Further Reflection

Что напечатает следующая программа, которая создаёт новый экземпляр объекта используя reflection?
public class Outer {
public static void main(String[] args) throws Exception {
new Outer().greetWorld();
}
private void greetWorld() throws Exception {
System.out.println(Inner.class.newInstance());
}
public class Inner {
public String toString() {
return "Hello world";
}
}
}

Программа напечатает Exception stack trace. А всё потому, что для вложенных (не статических!) классов не действует правило создания конструктора без параметров. В этом случае автоматически добавляется параметр, имеющий тип внешнего класса. Перепишем метод правильным образом:
  private void greetWorld() throws Exception {
Constructor c = Inner.class.getConstructor(Outer.class);
System.out.println(c.newInstance(this));
}

Обратите внимание, что в этом случае можно создать вложенный класс, для которого не установлен экземпляр внешнего класса. Надо только передать null вместо this. Автор рекомендует вообще не использовать reflection для создания экземпляров вложенных классов. Я бы сказал по другому: не используйте то, в чём не разбираетесь.
Тут автор ссылается на раздел 18 своей предыдущей книги Эффективное программирование: старайтесь использовать статические члены класса, когда это возможно.

Java Puzzle 79: It's a Dog's Life

Следующий класс моделирует жизнь домашнего животного. В самом задании забавная игра слов: обычно собаки бегают на заднем дворе (run in the backyard), а наша будет выполняться в фоновом режиме (run in the background). Что программа напечатает?
public class Pet {
public final String name;
public final String food;
public final String sound;
public Pet(String name, String food, String sound) {
this.name = name;
this.food = food;
this.sound = sound;
}
public void eat() {
System.out.println(name + ": Mmmmm, " + food);
}
public void play() {
System.out.println(name + ": " + sound + " " + sound);
}
public void sleep() {
System.out.println(name + ": Zzzzzzz...");
}
public void live() {
new Thread() {
public void run() {
while (true) {
eat();
play();
sleep();
}
}
}.start();
}
public static void main(String[] args) {
new Pet("Fido", "beef", "Woof").live();
}
}

Компилятор найдёт метод с именем sleep в классе Thread и перестанет искать дальше. А так как метод sleep должен принимать параметры, то компилятор тут и ругнётся. Эта проблема называется затенением (shadowing) и описана в спецификции (JLS 6.3.1). Почему так было сделано - история умалчивает. Чтобы программа скомпилировалась можно самому разрезолвить этот метод: Pet.this.sleep(). Но в данном случае лучший совет - не переопределяйте класс Thread, а реализуйте интерфейс Runnable и используйте его для создания нити:
  public void live() {
new Thread(new Runnable() {
public void run() {
while (true) {
eat();
play();
sleep();
}
}
}).start();
}

Великий Пост

Несколько дней назад покупали в Карусели кисель для Мишки. А на нём наклейка, что продукт рекомендуется в великий пост. Я ещё пошутил, что написали бы, что освящено...
И что бы вы думали! Сегодня Юля в магазине купила упаковку морской капусты, на которой круглая наклейка с надписью: Освящено священником Александром из церкви Св. Вмч. Георгия Победоносца в Купчино. Во дают!

четверг, 27 марта 2008 г.

Michael Pinnella


Вот и ещё один альбом был куплен только потому, что в Кайласе НЕТ свежих дисков: Enter By The Twelfth Gate (2004). Это инструментальный альбом клавишника группы Symphony X. В нём отсутствуют какие бы то ни было элементы хэви-метал. После первого прослушивания альбом оставил какие-то непонятные впечатления. Я даже решил убрать его подальше, но послешав его ещё пару раз почувствовал, что альбом очень и очень неплох. Слушать его приятно, а какие-то претензии могут возникнуть лишь к звуковому решению. И программированные барабаны не слишком портят впечатление от пластинки.

Нет вдохновения

Что-то я давненько ничего не сочинял. В голове один мотив про бегемота из Смешариков, которые Мишка ежедневно смотрит. Вот на этот мотив и сочинилось:
    Если ты хочешь стихи сочинять,
    То для начала учись рифмовать.
    Выбери тему стиха и мотив...
    И начинай сочинять креатив!
Или позитив. Кому как нравится...

Культурный тест

Раз уж и Стас и Юля прошли тест, то и я тоже попытался. Забавно, что у нас совершенно разные результаты:
Поздравляем!!! Вам ближе славянская культура
Вы по-настоящему русский человек! Вам вполне комфортно в России, и это очень хорошо, когда человек живет в обществе, ценности которого разделяет. image
Пройти тест

Supaplex

Помнится в общаге любил играть в Supaplex. Это такая игра под DOS в стиле Boulder Dash. Но потом, при переходе на Windows NT я забыл про эту игру, так как не работает она под Win32 API. И вот выясняется, что есть ещё фанаты, которые портировали её под Windows XP. Встречайте - WinPlex:

Кроме того, на этом сайте можно скачать редактор и кучу уровней к игре, которые до сих пор создаются фанатами...

среда, 26 марта 2008 г.

Blizzard

Вчера вечером возвращался домой - была суровая метель. Очень сильный ветер с мелкими ледяными градинами. Получил хороший крио-массаж лица.
С утра шёл на работу - сугробы подтаяли. Под ними организовались огромные лужи, которых не видно, так как сверху всё ещё снег лежит. Пока дошёл до работы промочил ноги. Лучше промочить горло, чем ноги!
Ветер днём был не сильный. Говорят, что в Москве он был гораздо сильнее. Коты выпали осадками...
Ну а сегодня вечером опять ударил мороз и везде был лёд. Еле до дому дошёл. Заносило на поворотах ;)
Автомобилистам хреново. У нас на работе один коллега уже успел переобуться в летнюю резину. Вот ему удовольствие будет ехать в Финляндию на выходных...

понедельник, 24 марта 2008 г.

Java Puzzle 78: Reflection Infection

Рассмотрим простое применение refletion. Что напечатает следующая программа?
import java.lang.reflection.*;
import java.util.*;
public class Reflector {
public static void main(String[] args)
throws Exception {
Set set = new HashSet();
set.add("foo");
Iterator it = set.iterator();
Class type = it.getClass();
Method method = type.getMethod("hasNext");
System.out.println(method.invoke(it));
}
}

Нашли, блин, чем меня удивить! Я с такими проблемами в JavaBeans регулярно сталкиваюсь. Несмотря на то, что метод определён как public, он определён в private классе. И у пользователя просто нет прав, чтобы его вызвать. Приходится рекурсивно проходить по иерархии классов и интерфейсов и искать его пототип, который действительно разрешён к использованию. Обратите внимание, что еcли метод получить другим образом, то он будет работать:
    Method method = Iterator.class.getMethod("hasNext");

Java Puzzle 77: The Lock Mess Monster

Разберитесь-ка, как работает следующая программа:
import java.util.*;
public class Worker extends Thread {
public static void main(String[] args)
throws InterruptedException {
final Worker worker = new Worker();
worker.start();
Timer timer = new Timer(true);
timer.schedule(
new TimerTask() {
public void run() {
worker.keepWorking();
}
}, 500);
sleep(400);
worker.quit();
}
private volatile boolean stop = false;
public void run() {
while (!stop) pretendToWork();
System.out.println("Beer is good!");
}
private void pretendToWork() {
try {
sleep(300);
}
catch (InterruptedException exception) {
}
}
synchronized void keepWorking() {
stop = false;
}
synchronized void quit() {
stop = true;
join();
}
}

Беглый анализ показывает, что где-то через секунду программа напишет Beer is good! и завершит свою работу. Но на самом деле она зависает! Проблема в том, что внутренняя реализация метода join вызывает метод wait на экземпляре класса Thread, который должен быть присоединён. А вызов метода wait снимает блокировку!
Фундаментальная причина ошибочного поведения класса Worker - использование блокировки по экземпляру (synchronized методы). Не полагайтесь на поведение библиотеки - делайте собственные объекты блокировки, которые не доступны никому другому. Это напоминает раздел 15 книги Эффективное программирование Джошуа Блоха.

воскресенье, 23 марта 2008 г.

Снеговики

Вчера вечером, возвращаясь из гаража, зашли в магазин. Юля пошла за продуктами, а мы с Мишкой остались на улице лепить снеговика. Мишку это очень зацепило. Видимо, по снегу соскучился...
Сегодня с утра ездили к зубному на профилактический осмотр. Пока Юлю осматривали, я с Мишкой слепили двух снеговиков (большого и маленького). Мишка вовсю лепил носы, щёки, уши (они же руки;). Потом они с Юлей третьего снеговика слепили, пока меня доктор осматривал. Мишка спросил Юлю: "А почему мама такая маленька вышла?". Просёк, что большой снеговик - папа, маленький - Мишка, ну а чуть побольше - мама:

А из клиники улыбаясь за нами наблюдали охранник, гардеробщица и девчонки с рецепшн. Наши снеговики прямо напротив входа стоят на Комендантском, 17. Надеюсь, мы народу настроение хорошо подняли!

суббота, 22 марта 2008 г.

Погода

С утра была замечательная солнечная погода. Мы даже заехали на автомойку, но там была толпа автолюбителей. Ну мы и поехали грязными, так как надо было съездить по делам к определённому времени. Пока Юля занималась делами, мы с Мишкой сопели в машине на солнышке. Потом поехали к Паше с Ирой в гости, где Мишка показывал высший пилотаж в Paint:

Вечером, когда вышли от Пашки, обнаружили, что выпал снег. Машинку хорошо так залепило снегом. Мы почистились и поехали. Хорошо, что не помылись...
На обратном пути видели несколько аварий на Кольцевой. В одной аварии аж 5 машин было. Аккурат за знаком ограничения скорости 80. Народ-то подумал, что зима кончилась, и шины поменял на летние. Ну и огрёб...

среда, 19 марта 2008 г.

Alice Cooper


Заехал в Кайлас на днях, а там опять ничего нового. В этот раз мне под руку подвернулся альбом Dirty Diamonds (2005).
Не стареют душой ветераны! Вот и старина Элис Купер до сих пор пишет песни, хотя ему скоро стукнет 60 лет. Это его 24-ый альбом, но уж больно он напоминает старые диски. Сразу ностальгия охватывает...
Однако, нельзя сказать, что диск занудный. Он очень разноплановый, хотя и спокойный. Весьма позитивный и слегка старомодный. Что-то в нём есть такое...

суббота, 15 марта 2008 г.

Чеширский кот

Хороший аватар, когда злобное настроение ;)

Metallica tribute

Смотреть до конца:

четверг, 13 марта 2008 г.

Тестируем замену Skype

Написал мне тут мой бывший коллега, который проработал в STAR семь с половиной лет. Попросил потестировать его текущий проект. Можно звонить по межгороду с компа практически на любой номер. Говорит, что Эстония тоже поддерживается...
Позвонив на домашний телефон я обнаружил, что качество связи хромает, чем немало удивил его. Завтра потестирую связь с Таллинном...
Если будете тестировать - пишите результат: откуда звонили, с какого провайдера, в какой город, на домашний или мобильный, ну и про качество связи не забывайте. Говорить можно, пока, минуту. Потом связь останется бесплатной, но за просмотр рекламного ролика...

Java Puzzle 76: Ping Pong

Следующая программа содержит синхронизированные статические методы. Что она напечатает? Гарантируется ли её результат от запуска к запуску?
public class PingPong {
public static synchronized void main(String[] args) {
Thread thread = new Thread() {
public void run() {
pong();
}
};
thread.run();
System.out.print("Ping");
}
static synchronized void pong() {
System.out.print("Pong");
}
}

Начнём с того, что синхронизировав статические методы мы добились того, что результат программы гарантируется от запуска к запуску. Но почему она пишет PongPing вместо PingPong?
Типичная ошибка и простая невнимательность. Для запуска отдельного потока надо вызывать метод start, а не метод run. В нашем случае всё действие происходит на одном потоке.
Будьте внимательны!