Статическая переменная пытается получить доступ к другой статической переменной - PullRequest
1 голос
/ 02 июля 2010

Мне было интересно, безопасен ли следующий код.

public class GUIBundle {

    // The technique known as the initialization on demand holder idiom, 
    // is as lazy as possible.
    // http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
    //private static class BundleHolder {
    //    private static final ResourceBundle bundle = ResourceBundle.getBundle("org.yccheok.jstock.data.gui");
    //}
    private static final ResourceBundle bundle = ResourceBundle.getBundle("org.yccheok.jstock.data.gui");

    private GUIBundle() {
    }

    public static String getString(String key) {
        // return BundleHolder.bundle.getString(key);
        return bundle.getString(key);
    }
}

public class SellPortfolioChartJDialog extends javax.swing.JDialog {

    private static final String[] cNames = new String[] {
        GUIBundle.getString("BuyPortfolioTreeTableModel_NetGainValue")
    };
}

Поскольку cNames находится в статической области видимости, безопасен ли для него доступ к статическому пакету? Есть ли разница, использую ли я ленивую технику инициализации?

Я помню, что натолкнулся на статью (я все равно потерял статью), в которой говорилось о недетерминированном порядке инициализации статических переменных. Я не уверен, был ли недетерминирован порядок инициализации статических переменных, примененный к вышеуказанному случаю?

Ответы [ 4 ]

4 голосов
/ 02 июля 2010

Я считаю, что недетерминированный порядок инициализации статических переменных (в разных единицах компиляции) является "особенностью" C / C ++. В Java статические переменные инициализируются при загрузке их класса и внутри одного класса в порядке их объявления. Таким образом, порядок является детерминированным (по крайней мере, в однопоточной среде).

Это гарантирует, что то, что вы намереваетесь сделать, должно работать: при первом обращении к GUIBundle загрузчик классов загружает его и также инициализирует bundle. Вызов GUIBundle.getString() происходит только после инициализации класса.

1 голос
/ 02 июля 2010

Я думаю, что это совершенно безопасно, вы видите, потому что, когда

GUIBundle.getString

используется в вашем подклассе JDialog, JVM будет полностью инициализировать (см. Загрузку спецификации языка Java, связывание и инициализацию) класс GUIBundle передвызывая для него метод getString, который инициализирует все инициализаторы класса (статические) в классе GUIBundle.

Редактировать: Подробнее об этом см. в спецификации ВМ: http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#16491

1 голос
/ 02 июля 2010

Это работает просто отлично. Я получил его для компиляции, придерживаясь того же принципа, но используя разные классы (я не хотел беспокоиться о том, чтобы получить ваши банки ...: -).

Очевидно, что есть небольшие проблемы, например, как вы объявляете, что ваша строка [] должна быть

private static final String[] cNames = new String[] {
        GUIBundle.getString("BuyPortfolioTreeTableModel_NetGainValue")
    };
}

Кроме этого, он работает просто отлично. Ключ к использованию статики в других статиках - это порядок, в котором они объявлены. Вы не можете сделать это

static Foo b = a;
static Foo a = new Foo();
0 голосов
/ 02 июля 2010

Для меня это безопасно.

bundle инициализируется сразу после загрузки GUIBuilder и, следовательно, до того, как getString вызывается впервые.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...