четверг, 4 октября 2007 г.

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"));
    }
}
Программа напечатает: [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 и инициализацию этого поля из конструктора)

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

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