java поля Должен ли я инициализировать переменную внутри конструктора или внешнего конструктора



конструктор java (9)

Когда я использую Java на основе моих знаний на C ++, я люблю инициализировать переменную следующим образом.

public class ME {
    private int i;

    public ME() {
         this.i = 100;
    }
}

Когда-то я меняю привычку на

public class ME {
    private int i = 100;

    public ME() {
    }
}

Я натолкнулся на другие исходники, некоторые используют 1-е соглашение, другие используют 2-е соглашение.

Могу ли я узнать, какую конвенцию вы все рекомендуете, и почему?


Answer #1

Я нахожу второй стиль (декларация + инициализация за один раз) выше. Причины:

  • Это дает понять, как инициализируется переменная. Как правило, при чтении программы и пересечении переменной вы сначала переходите к ее объявлению (часто автоматически в IDE). Со стилем 2 вы сразу увидите значение по умолчанию. В стиле 1 вам также нужно посмотреть на конструктор.
  • Если у вас несколько конструкторов, вам не нужно повторять инициализации (и вы не можете их забыть).

Конечно, если значение инициализации отличается в разных конструкторах (или даже вычисляется в конструкторе), вы должны сделать это в конструкторе.


Answer #2

Я думаю, что оба правильные программы мудры,

Но я думаю, что ваш первый вариант более корректен объектно-ориентированным образом, потому что в конструкторе это когда объект создается, и именно тогда инициализируется переменная.

Я думаю, что это конвенция «по книге», но она открыта для обсуждения.

Wikipedia


Answer #3

Я рекомендую инициализировать переменные в конструкторах. Вот почему они существуют: чтобы ваши объекты были построены (инициализированы) правильно.

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


Answer #4

У меня есть практика (привычка) почти всегда инициализации в contructor по двум причинам: одна, по моему мнению, добавляет readablitiy (чище), а два больше логического управления в конструкторе, чем в одной строке. Даже если изначально переменная экземпляра не требует логики, ее наличие в конструкторе дает большую гибкость для добавления логики в будущем, если это необходимо.

Что касается упомянутой выше проблемы о нескольких конструкторах, это легко решить, если у вас есть один конструктор no-arg, который инициализирует все переменные экземпляра, которые инициализируются одинаково для всех конструкторов, а затем каждый конструктор вызывает это () в первой строке. Это решает проблемы с удалением.


Answer #5

Я бы сказал, это зависит от дефолта . Например

public Bar
{
  ArrayList<Foo> foos;
}

Я бы сделал new ArrayList вне конструктора, если я всегда предполагаю, что foos не может быть нулевым. Если Bar является допустимым объектом, не заботясь о том, является ли foos нулевым или нет, я бы поместил его в конструктор.

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


Answer #6

Если вы инициализируетесь в верхней части или в конструкторе, это не имеет большого значения. Но в некоторых случаях инициализация в конструкторе имеет смысл.

class String
{
    char[] arr/*=char [20]*/; //Here initializing char[] over here will not make sense.
    String()
    {
        this.arr=new char[0];
    }
    String(char[] arr)
    {
        this.arr=arr;
    }
}

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

FYI другой вариант для инициализации без использования конструктора:

class Foo
{
    int i;
    static int k;

    //instance initializer block
    {
        //run's every time a new object is created
        i=20;
    }

    //static initializer block
    static{
        //run's only one time when the class is loaded
        k=18;
    }    
} 

Answer #7

Это может зависеть от того, что вы инициализируете, например, вы не можете просто использовать инициализацию поля, если задействовано исключенное исключение. Например, следующее:

public class Foo {
    FileInputStream fis = new FileInputStream("/tmp"); // throws FileNotFoundException
}

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

public Foo() throws FileNotFoundException {} 

Answer #8

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


Answer #9

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

Например, во втором фрагменте вы можете удалить конструктор и получить более четкий код.





java