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

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();
    }
}

Комментариев нет:

Отправить комментарий