2014-12-30 2 views
-1

Я уже более 2 лет программирую на Java, и я просто решил уделять пристальное внимание деталям для переменных-членов, и это вызывало у меня любопытство о том, как инициализируется класс.Порядок инициализации Java-класса

Я работаю над игрой, и в моем классе, GameStateMenu, который простирается GameState, у меня есть переменная-член:

private int buttonPadding = 10; 

У меня есть init() метод, унаследованный силу с superclass (вызывается из superclass constructor), и если я вызываю System.out.println(buttonPadding) внутри этого метода init(), он печатает 0.

Там также update() метод внутри GameStateMenu класса, и я ставлю ту же строку кода, System.out.println(buttonPadding), внутри него, и он продолжает распечатывания 10.

GameState класс:

public abstract class GameState { 

    public GameState() { 
     init(); 
    } 

    protected abstract void init(); 

    public abstract void load(); 

    public abstract void update(); 

    public abstract void render(); 

    public void dispose() { 
     return; 
    } 
} 

GameStateMenu класс:

public class GameStateMenu extends GameState { 

    ... 
    private int buttonPadding = 10; 

    @Override 
    protected void init() { 
     System.out.println(buttonPadding); // prints out 0 
     ... 
    } 

    ... 

    @Override 
    public void update() { 
     System.out.println(buttonPadding); // prints out 10 
     ... 
    } 
    ... 
} 

Что я не понимаю, так это wh y buttonPadding - 0, когда вызывается метод init(), но как только класс полностью инициализирован, и вызывается метод update(), регулярно, buttonPadding был инициализирован и распечатывается 10. Почему он делает это и/или какой порядок инициализации для Java?

Хотя, если я сделал buttonPadding статический, он работает правильно, но мне все еще интересно, почему переменная-член не установлена.

+0

Возможно, вам захочется создать пример [минимального кода] (http://stackoverflow.com/help/mcve) для более четкой демонстрации ситуации. – Sebi

+0

Можете ли вы опубликовать фактический код? Я немного смущен вашим описанием. Если buttonPadding - глобальная переменная, я думаю, что ее нужно объявить 'static', иначе это фактически переменная-член, и GameState не будет иметь к ней доступа. – Dtor

+0

Я обновил сообщение с помощью некоторого кода и исправил свой грамматик, назвав его «глобальной переменной» вместо «переменной-члена». – CoderMusgrove

ответ

2

Родительский класс (GameState) полностью инициализируется перед дочерним классом (GameStateMenu). Это значит, что конструктор GameState вызывается до того, как любая инициализация происходит в GameStateMenu, поэтому в этой точке buttonPadding по-прежнему имеет значение по умолчанию для неназначенного int, равного нулю. После того, как GameState полностью инициализируется, GameStateMenu получает инициализацию - сначала buttonPadding получает значение 0, затем вызывает вызов конструктора.

Unsolicited Advice: Как правило, Bad Idea для конструктора родительского класса вызывать методы, определенные в дочерних классах. Это позволяет дочерним классам прерывать инварианты родителя. В этом конкретном случае похоже, что вам нужен интерфейс вместо абстрактного класса, но трудно сказать, не зная больше о вашем коде.