среда, 7 ноября 2007 г.

Железная дорога

Мои родители подарили Мишке набор Кроха - Железная дорога. Мы докупили еще деталей и получаются различные конфигурации. Мишка очень доволен!

Шкаф для дисков

Шкаф для обуви

Java Puzzle 56: Big Problem

Проверим знание класса BigInteger. Что напечатает следующая программа?
BigInteger value = new BigInteger("1000000");
value.add(new BigInteger("1000000"));
System.out.println(value);

А вот и нет! Не 2 миллиона, а всего 1. Авторы данного API использовали не вполне корректные имена для методов неизменяемого (immutable) объекта, что и вводит пользователей в заблуждение. Чтобы исправить ошибку надо сделать так:
BigInteger value = new BigInteger("1000000");
value = value.add(new BigInteger("1000000"));
System.out.println(value);

Java Puzzle 55: Creationism

Иногда полезно для класса знать количество экземпляров, которые были созданы. Следующая программа демонстрирует эту технику. Что будет напечатано?
public class Creator {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++)
            Creature creature = new Creature();
        System.out.println(Creature.getCount());
    }
}
class Creature {
    private static long count = 0;
    public static long getCount(String[] args) {
        return count;
    }
    public Creature() {
        count++;
    }
}

Программа не скомпилируется, так как декларация локальной переменной допустима только внутри блока (JLS 14.12-14). Декларацию можно убрать, используя только создание объекта, так как локальная переменная все равно не используется.
Кроме того, авторы не рекомендуют использовать int как тип счетчика, чтобы избежать переполнения. Максимум для типа int - 231 - 1 (около 2.1 * 109), а для типа long - 263 - 1 (около 9.2 * 1018). Сейчас компьютеры способны создавать около 108 объектов в секунду. Следовательно переполнение для типа long произойдет через три тысячи лет.
Также авторы рекомендуют использовать thread-safe вариант:
class Creature {
    private static long count = 0;
    public static long getCount(String[] args) {
        synchronized (Creature.class) {
            return count;
        }
    }
    public Creature() {
        synchronized (Creature.class) {
            count++;
        }
    }
}
В Java 5 и выше можно использовать класс AtomicLong:
import java.util.concurrent.atomic.AtomicLong;
class Creature {
    private static final AtomicLong count = new AtomicLong();
    public static long getCount(String[] args) {
        return count.get();
    }
    public Creature() {
        count.incrementAndGet();
    }
}