Различные способы инициализации переменных в Java

Я натолкнулся на код guessgame. Существует фрагмент кода, в котором три объекта игрока инициализируются следующим образом:

public class guessgame{
    Player p1;
    Player p2;
    Player p3;
    public void startGame() {
        p1 = new Player();
        p2 = new Player();
        p3 = new Player();
    ...
    }
    ...
}

То же самое срабатывало, когда я объявил и инициировал его следующим образом.

public class GuessGame {
    Player p1 = new Player();
    Player p2 = new Player();
    Player p3 = new Player();
    public void startGame(){
        ...
    }
    ...
}

Есть ли разница между этими двумя? В первом примере, почему три переменные экземпляра были объявлены вне метода startgame(), и действительно ли это имеет значение внутри?

Ответ 1

Есть ли разница между двумя?

Да. Код в первом фрагменте будет выполняться только в контексте startGame. Если вы не вызываете startGame, объекты остаются null. Каждый раз, когда вы вызываете startGame, старые объекты, если они есть, будут отброшены и заменены новыми.

Второй фрагмент будет выполняться один раз для каждого объекта GuessGame при вызове любого из его конструкторов. Код будет разделяться между всеми конструкторами.

В первом примере почему три переменные экземпляра, объявленные вне метода startGame()

Единственный способ объявить переменную экземпляра - это сделать это вне метода. Переменные, объявленные внутри метода, являются локальными.

Другим отличием первого и второго способов является то, что вызов методов экземпляра, которые обращаются к игрокам, становится "законным" только после вызова startGame в первом фрагменте кода.

Ответ 2

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

Если вы никогда не вызываете startgame(), то вы откладываете выделение его, и, возможно, пользователь никогда не хочет запускать игру. Это разумно, если игрокам требуется много памяти для сборки, и вы не хотите, чтобы пользователь дождался этого события (выделение памяти) и сразу же запускал методы (которые их не используют).

Если по какой-то причине у вас есть несколько методов, которые должны использовать переменные p1, p2, p3, то координация того, кто будет инициализироваться, может ввести в заблуждение, поэтому вы можете просто укусить пулю и инициализировать ее заранее. Если вы знаете, что будет 3 игрока, зачем беспокоиться о методах? В противном случае вам нужно будет сделать что-то вроде:

if (p1 == null){
    p1 = new Player();
}

Ответ 3

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

Ответ 4

В первом примере объекты создаются только при вызове метода startGame(). Перед вызовом этого метода p1, p2 и p3 равны null.

В вашем втором примере вы объявляете и создаете экземпляр непосредственно. Поэтому они создаются при создании класса.

Ответ 5

1st: Инициализация при методе startGame()

guessgame gg = new guessgame() // Here p1 is null

2nd: на уровне класса

GuessGame GG = new GuessGame() // OK p1 is initialized

Ответ 6

p1, p2, p3 не являются локальными переменными, а полями классов.

Они доступны для всех методов класса после создания экземпляра класса.

В первом фрагменте значения трех полей: null, пока не будет вызван метод startGame().

Во втором фрагменте поля инициализируются при построении экземпляра.