Порядок инициализации статических переменных

В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не самими объектами.

При попытке выполнить один метод объекта , ссылка просит живой объект выполнить этот метод. Но если ссылка ссылается на NULL (ничего, нуль, void, nada), то нет способа, которым метод будет выполнен. Тогда runtime сообщит вам об этом, выбросив исключение NullPointerException.

Ваша ссылка «указывает» на нуль, таким образом, «Null -> Pointer».

Объект живет в памяти виртуальной машины пространство и единственный способ доступа к нему - использовать ссылки this. Возьмем этот пример:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

И в другом месте вашего кода:

Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

Это важно знать - когда больше нет ссылок на объект (в пример выше, когда reference и otherReference оба указывают на null), тогда объект «недоступен». Мы не можем работать с ним, поэтому этот объект готов к сбору мусора, и в какой-то момент VM освободит память, используемую этим объектом, и выделит другую.

59
задан umlcat 4 August 2014 в 17:42
поделиться

4 ответа

Поскольку Вы говорите, что порядок не определен через различные единицы компиляции.

В той же единице компиляции порядок четко определен: тот же порядок как определение.

Это вызвано тем, что это не разрешено на уровне языка, но на уровне компоновщика. Таким образом, действительно необходимо проверить документацию компоновщика. Хотя я действительно сомневаюсь, что это поможет любым полезным способом.

Для gcc: Выезд ld

, я нашел, что даже изменение порядка связываемых файлов объектов может изменить порядок инициализации. Таким образом, это не просто Ваш компоновщик, которого необходимо взволновать по поводу, но как компоновщик вызывается системой сборки. Даже попытайтесь решить проблему, практически не начинающий.

Это - вообще только проблема при инициализации globals, что ссылка друг друга во время их собственной инициализации (поэтому только влияет на объекты с конструкторами).

существуют методы для обхождения проблемы.

  • Ленивая инициализация.
  • Счетчик Schwarz
  • Помещенный все сложные глобальные переменные в той же единице компиляции.
<час>
  • Примечание 1: globals:
    Используемый свободно для обращения к статическим переменным продолжительности хранения, которые потенциально инициализируются прежде main().
  • Примечание 2: Потенциально
    В общем случае мы ожидаем, что статические переменные продолжительности хранения будут инициализированы перед основным, но компилятору позволяют задержать инициализацию в некоторых ситуациях (правила сложны, см. стандарт для деталей).
69
ответ дан Martin York 24 November 2019 в 18:24
поделиться

Я ожидаю, что порядок конструктора между модулями является главным образом функцией того, какой порядок Вы передаете объекты компоновщику.

Однако GCC действительно позволяет Вам использование init_priority для явного определения упорядочивания для глобального ctors:

class Thingy
{
public:
    Thingy(char*p) {printf(p);}
};

Thingy a("A");
Thingy b("B");
Thingy c("C");

выводы 'ABC', как Вы ожидали бы, но

Thingy a __attribute__((init_priority(300))) ("A");
Thingy b __attribute__((init_priority(200))) ("B");
Thingy c __attribute__((init_priority(400))) ("C");

выводы 'BAC'.

18
ответ дан underscore_d 24 November 2019 в 18:24
поделиться

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 - эта ссылка перемещается. этот один более стабильно, но необходимо будет навести справки о нем.

редактирование: osgx предоставил лучшее ссылка .

4
ответ дан Ray Tayek 24 November 2019 в 18:24
поделиться

В дополнение к комментариям Martin, происходящим из среды C, я всегда думаю о статических переменных как о части исполняемого файла программы, включенного и выделенного места в сегменте данных. Таким образом статические переменные могут считаться как инициализируемый загрузками программы до любого выполненного кода. Точный порядок, в котором это происходит, может быть установлен путем рассмотрения сегмента данных файла карты, произведенного компоновщиком, но для большинства намерений, и имеет целью инициализацию, simultaeneous.

Редактирование: В зависимости от порядка конструкции статических объектов склонно быть непортативным и должен, вероятно, избежаться.

1
ответ дан SmacL 24 November 2019 в 18:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: