суббота, 6 октября 2007 г.
Отпуск
Сегодня первый день отпуска. Сначала по Питеру погуляем, потом в Таллинн на недельку смотаемся. Доступ к компу будет очень ограниченный...
четверг, 4 октября 2007 г.
id Software
Небезызвестная id Software недавно выпустила многопользовательский шутер Enemy Territory Quake Wars. И просочилась информация о следующем проекте - Rage.
Rage поведает о нелегкой борьбе главного героя с тоталитарным правительством в постапокалиптическом мире (привет Fallout). В отличие от предыдущих проектов id Software, это первая игра, которая отойдет от привычного "коридорного" стиля, позволив игроку свободно гулять пешком и кататься на машинах по открытым пространствам. Иллюзия свободы станет возможной благодаря новому движку id Tech 5, главная способность которого - отрисовка больших площадей с большим количеством деталей, видимостью до горизонта и безо всяких "тормозов".
id Software не огласила ни дату выхода Rage, ни имя ее издателя. Последнее стало сюрпризом, ведь студия уже много лет сотрудничает с компанией Activision. Судя по тому, что недавно они запустили в Steam почти все свои проекты, начиная с Commander Keen и заканчивая Doom 3: Resurrection of Evil, возможно, что Кармак решил заняться цифровым самиздатом.
Rage поведает о нелегкой борьбе главного героя с тоталитарным правительством в постапокалиптическом мире (привет Fallout). В отличие от предыдущих проектов id Software, это первая игра, которая отойдет от привычного "коридорного" стиля, позволив игроку свободно гулять пешком и кататься на машинах по открытым пространствам. Иллюзия свободы станет возможной благодаря новому движку id Tech 5, главная способность которого - отрисовка больших площадей с большим количеством деталей, видимостью до горизонта и безо всяких "тормозов".
id Software не огласила ни дату выхода Rage, ни имя ее издателя. Последнее стало сюрпризом, ведь студия уже много лет сотрудничает с компанией Activision. Судя по тому, что недавно они запустили в Steam почти все свои проекты, начиная с Commander Keen и заканчивая Doom 3: Resurrection of Evil, возможно, что Кармак решил заняться цифровым самиздатом.
Октябрятам - привет!
Так сложилось, что у многих моих знакомых дни рождения в октябре. У Саши Поточкина и Сереги Александрова вчера случился, у Стаса Торгашова - сегодня. 7-го будет 56 лет моему отцу. Всем мои поздравления!
Java Puzzle 52: Sum Fun
class Cache {
static {
initIfNeeded();
}
private static int sum;
public static int getSum() {
initIfNeeded();
return sum;
}
private static boolean inited = false;
private static void initIfNeeded() {
if (!inited) {
for (int i = 0; i <100; i++) {
sum += i;
}
inited = true;
}
}
}
class Main {
public static void main(String[] args) {
System.out.println(Cache.getSum());
}
}
Программа напечатает не 4950, а 9900. Это не то, что автор такого класса хотел. Весь прикол в том, что JVM инициализирует статические переменные в классе последовательно. Сначала вызывается статический блок, в котором устанавливается значение sum и inited. Затем пропускается инициализация sum. После чего inited принудительно инициализируется в false. Таким образом, при вызове getSum будет повторно увеличено значение sum. Для того, чтобы этого не произошло, надо объявить sum так:
private static int sum = 0;
или же объявить inited так:
private static boolean inited;
А вообще так делать не рекомендуется. Лучше сделать так:
class Cache {
private static final int SUM = calculate();
public static int getSum() {
return SUM;
}
private static int calculate() {
int sum = 0;
for (int i = 0; i <100; i++) {
sum += i;
}
return sum;
}
}
static {
initIfNeeded();
}
private static int sum;
public static int getSum() {
initIfNeeded();
return sum;
}
private static boolean inited = false;
private static void initIfNeeded() {
if (!inited) {
for (int i = 0; i <100; i++) {
sum += i;
}
inited = true;
}
}
}
class Main {
public static void main(String[] args) {
System.out.println(Cache.getSum());
}
}
Программа напечатает не 4950, а 9900. Это не то, что автор такого класса хотел. Весь прикол в том, что JVM инициализирует статические переменные в классе последовательно. Сначала вызывается статический блок, в котором устанавливается значение sum и inited. Затем пропускается инициализация sum. После чего inited принудительно инициализируется в false. Таким образом, при вызове getSum будет повторно увеличено значение sum. Для того, чтобы этого не произошло, надо объявить sum так:
private static int sum = 0;
или же объявить inited так:
private static boolean inited;
А вообще так делать не рекомендуется. Лучше сделать так:
class Cache {
private static final int SUM = calculate();
public static int getSum() {
return SUM;
}
private static int calculate() {
int sum = 0;
for (int i = 0; i <100; i++) {
sum += i;
}
return sum;
}
}
Java Puzzle 51: What's the Point
class Point {
private final int x, y;
private final String name; // cached at construction time
Point(int x, int y) {
this.x = x;
this.y = y;
this.name = makeName();
}
protected String makeName() {
return "[" + this.x + "," + this.y + "]";
}
public final String toString() {
return this.name;
}
}
class ColorPoint extends Point {
private final String color;
ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}
protected String makeName() {
return super.makeName() + ":" + this.color;
}
public static void main(String[] args) {
System.out.println(new ColorPoint(4, 2, "purple"));
}
}
Программа напечатает:
Этот паззл показывает, что возможно получить значение final переменной до того, как она буде проинициализирована. Для того, чтобы избежать этой проблемы, никогда не вызывайте из конструктора те методы, которые можно перекрыть (напрямую или косвенно). Автор ссылается на свою предыдущую книгу Effective Java.
Для решения проблемы с производительностью в данном случае лучше всего использовать lazy initialization:
public final synchronized String toString() {
if (this.name == null) {
this.name = makeName();
}
return this.name;
}
(еще надо убрать final перед декларацией поля name и инициализацию этого поля из конструктора)
private final int x, y;
private final String name; // cached at construction time
Point(int x, int y) {
this.x = x;
this.y = y;
this.name = makeName();
}
protected String makeName() {
return "[" + this.x + "," + this.y + "]";
}
public final String toString() {
return this.name;
}
}
class ColorPoint extends Point {
private final String color;
ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}
protected String makeName() {
return super.makeName() + ":" + this.color;
}
public static void main(String[] args) {
System.out.println(new ColorPoint(4, 2, "purple"));
}
}
Программа напечатает:
[4,2]:nullЭтот паззл показывает, что возможно получить значение final переменной до того, как она буде проинициализирована. Для того, чтобы избежать этой проблемы, никогда не вызывайте из конструктора те методы, которые можно перекрыть (напрямую или косвенно). Автор ссылается на свою предыдущую книгу Effective Java.
Для решения проблемы с производительностью в данном случае лучше всего использовать lazy initialization:
public final synchronized String toString() {
if (this.name == null) {
this.name = makeName();
}
return this.name;
}
(еще надо убрать final перед декларацией поля name и инициализацию этого поля из конструктора)
четверг, 27 сентября 2007 г.
Growl Karaoke
Если вам нравится петь караоке и вы уважаете тяжелый рок, то попробуйте Growl Karaoke. Даже если вы знаете, что такое Growl, текст может вас очень удивить. Лично меня это караоке на хи-хи пробивает...
среда, 26 сентября 2007 г.
Приехали
Вот мы и приехали из Москвы. Доехали за 12 часов. Получается все быстрее и быстрее. Правда, у Юли права под Тверью поменяли временное разрешение за превышение скорости на 65 км/ч. Дорога только что отремотирована, тачка хорошая, временный знак с ограничением видно плохо...
Автомобильный холодильник температуру держит нормально несмотря на то, что один раз выдернули из розетки и не сразу обнаружили. На обогрев его не тестировали, хотя и такая фишка в нем есть.
Жаль теперь не получится в Таллинн поехать на машине. Или же придется ждать прав месяц. А ведь погода не улучшается...
Автомобильный холодильник температуру держит нормально несмотря на то, что один раз выдернули из розетки и не сразу обнаружили. На обогрев его не тестировали, хотя и такая фишка в нем есть.
Жаль теперь не получится в Таллинн поехать на машине. Или же придется ждать прав месяц. А ведь погода не улучшается...
пятница, 21 сентября 2007 г.
четверг, 20 сентября 2007 г.
Java Puzzle 50: Not Your Type
public class Type1 {
public static void main(String[] args) {
String s = null;
System.out.println(s instanceof String);
}
}
Тут все просто. Оператор instanceof определен так, чтобы возвращать false, когда его левый операнд null. Этим многие пользуются, чтобы не делать дополнительных проверок на null.
public class Type2 {
public static void main(String[] args) {
System.out.println(new Type2() instanceof String);
}
}
Тут задачка посложнее и я пропустил тот факт, что оператор instanceof требует, чтобы оба операнда имели такой тип, чтобы один был подтипом другого. А программа не скомпилится.
public class Type3 {
public static void main(String[] args) {
Type3 value = (Type3) new Object();
}
}
Опять подколка. После предыдущей задачи можно решить, что программа не скомпилится. Так оно и было бы, если бы создавался объект типа String. Но в программе создается Object, наследником которого являются все классы, включая Type3. Однако, при попытке выполнения произойдет исключение ClassCastException.
public static void main(String[] args) {
String s = null;
System.out.println(s instanceof String);
}
}
Тут все просто. Оператор instanceof определен так, чтобы возвращать false, когда его левый операнд null. Этим многие пользуются, чтобы не делать дополнительных проверок на null.
public class Type2 {
public static void main(String[] args) {
System.out.println(new Type2() instanceof String);
}
}
Тут задачка посложнее и я пропустил тот факт, что оператор instanceof требует, чтобы оба операнда имели такой тип, чтобы один был подтипом другого. А программа не скомпилится.
public class Type3 {
public static void main(String[] args) {
Type3 value = (Type3) new Object();
}
}
Опять подколка. После предыдущей задачи можно решить, что программа не скомпилится. Так оно и было бы, если бы создавался объект типа String. Но в программе создается Object, наследником которого являются все классы, включая Type3. Однако, при попытке выполнения произойдет исключение ClassCastException.
Java Puzzle 49: Larger Than Life
Что напечатает следующая программа?
public class Person {
private final int age;
private static final Person PERSON = new Person();
private static final int YEAR
= Calendar.getInstance().get(Calendar.YEAR);
public Person() {
this.age = YEAR - 2000;
}
public static void main(String[] args) {
System.out.println("age = " + PERSON.age);
}
}
А программа напечатает не 7, а -2000!
Программа показывает, что можно наблюдать final static поле до того, как оно будет проинициализировано. И чтобы это исправить надо изменить порядок следования полей: поставить YEAR перед PERSON, так как создание экземпляра Person требует проинициализированной переменной YEAR.
public class Person {
private final int age;
private static final Person PERSON = new Person();
private static final int YEAR
= Calendar.getInstance().get(Calendar.YEAR);
public Person() {
this.age = YEAR - 2000;
}
public static void main(String[] args) {
System.out.println("age = " + PERSON.age);
}
}
А программа напечатает не 7, а -2000!
Программа показывает, что можно наблюдать final static поле до того, как оно будет проинициализировано. И чтобы это исправить надо изменить порядок следования полей: поставить YEAR перед PERSON, так как создание экземпляра Person требует проинициализированной переменной YEAR.
Русский сайт Лема
Когда будет сконструировано устройство, которое по желанию сможет понизить или повысить интеллект любого человека, то появится спрос на понижение интеллекта, раз утверждают, что самые счастливые - идиоты. С. Лем
Стройка
Рядом с нашим офисом уже год как строится новое здание центральной налоговой инспекции. Что самое забавное, его строят какие-то южные гастарбайтеры, которые живут прямо в бараках на этой стройке. Наверняка налогов не платят ;-)
Ну а их биотуалеты, видимо, исчерпали свой ресурс и воздух не озонируют...
Ну а их биотуалеты, видимо, исчерпали свой ресурс и воздух не озонируют...
Пробки
Что-то сегодня на Володарском мосту и в округе офигенная пробка. Видимо из-за того, что на КАДе грузовики покрытие повредили и осталась одна полоса. От дома до налоговой ехал 50 минут. За это время можно было дойти до метро, проехать пару станций и там еще пешочком пройтись. Обратно я так и делал.
Забавный способ объезда пробки по встречке видел. Разворачивается машина на встречку и по ней сдает задо до перекрестка. Там снова разворачивается и впихивается в поток. Уроды!
Забавный способ объезда пробки по встречке видел. Разворачивается машина на встречку и по ней сдает задо до перекрестка. Там снова разворачивается и впихивается в поток. Уроды!
Налоговая
Сегодня с утра пытался подать документы на налоговые вычеты. После всех остальных попыток я думал, что эта будет последняя. Фиг!
Мне сказали, что я заполнил все правильно, но они не принимают мое заявление, так как я должен подавать его по месту постоянной прописки, а не временной регистрации. Так лениво в Одинцово ехать, а бабла-то хочется...
Мне сказали, что я заполнил все правильно, но они не принимают мое заявление, так как я должен подавать его по месту постоянной прописки, а не временной регистрации. Так лениво в Одинцово ехать, а бабла-то хочется...
среда, 19 сентября 2007 г.
Я сделаю для тебя ночь
Видимо, в Microsoft работают любители барона Мюнхгаузена. Они активировали черный экран тьмы, который включается после часа работы на нелицензионной Vista.
Балтийский вокзал
Говорят, что Балтийский вокзал перекрыли - ищут бомбу. Народ возвращается в офис, так как на маршрутки не сесть - безумная давка. Оказалось, что один бдительный страж порядка принял за бомбу кипу журналов. Это, конечно, хорошо. Только пассажиры в час пик, я думаю, были очень недовольны. У нас, например, многие из Петергофа работают.
Java Puzzle 48: All I Get Is Static
Тут рассматривается другая прописная истина: статические методы не виртуальны. Авторы перекрывают статический метод класса в его потомке, приводят экземпляр потомка к типу родительского класса и вызывают статический метод. Естественно, что вызывается метод родительского класса. Для избежания таких проблем - никогда не перекрывайте статические методы! А я еще заявлю, что профессионалы никогда не вызовают статический метод используя экземпляр класса. Я бы вообще запретил это на уровне языка.
Java Puzzle 47: Well, Dog My Cats!
Ну про эту задачку я и писать ничего не хочу. Авторы завели в базовом классе статический метод, а в классах-потомках его вызывают и удивляются, почему счетчик увеличивается для обоих экземпляров класса. Естественно! Каждое статическое поле едино как для самого класса, так и для его потомков.
Das Experiment
На NoName пробежала ссылка - поставил качаться.
Подписаться на:
Сообщения (Atom)