член приватной строки, с чем инициализировать - PullRequest
0 голосов
/ 06 марта 2009

В Java, как лучше всего инициализировать приватные строковые члены

class A {
       private String mem = ??//
       private int num;
       A (int a) {
          this.num = a;
       }
       A (int a, String s) {
           this.num = a;
           this.mem  = s; //What if s is null (Is this a good practice)
       }

}

Ответы [ 8 ]

4 голосов
/ 06 марта 2009

Полностью зависит от того, что вы делаете ...

Задайте себе эти вопросы (всякий раз, когда вы делаете какую-либо переменную)

  • будет ли когда-либо меняться значение?
  • Каковы допустимые значения?

В этом случае, если «mem» и «num» никогда не изменятся, пометьте их как окончательные (вы всегда можете убрать финал позже, если обнаружите, что вам придется их менять).

Также в этом случае "mem" может когда-либо быть нулевым? Может ли num быть <0? </p>

Вот пример изменений, которые я мог бы внести:

класс А { закрытый финал String mem; private int num;

   A (final int a) 
   {
       this(a, null); 
   }

   A (final int a, 
      final String s) 
   {
       if(a < 0)
       {
           throw new IllegalAgumentException("a cannot be < 0, was: " + a);
       }

       num = a;
       mem = s; 
   }

}

3 голосов
/ 06 марта 2009

Есть хитрость с этим (и с большинством переменных на самом деле).

Если вы НИКОГДА не инициализируете переменную, вы фактически предоставляете компилятору больше информации.

В некоторых случаях вам нужно, но этот случай действительно интересен:

String s;

if(a==5)
    s="It was Five";
if(a==6)
    s="It was Six";

System.out.print(s);

Это очень плохой код, но изящная вещь в том, что Java поймает его и скажет вам: "Эй, есть хороший шанс, что вы получите этот отпечаток с нулем".

Если вы начали с одной из этих двух строк:

String s=null;
String s="";

Компилятор не мог бы помочь вам с этой ошибкой. (Маловероятно, что вы хотели напечатать "", не так ли?)

Правильное исправление, когда вы видите, что это сообщение «переменная, возможно, не была инициализирована», НЕ инициализирует строку как ноль или «». Необходимо убедиться, что в каждом возможном пути s установлено правильное значение:

if(a==5)
    s="It was Five";
else if(a==6)
    s="It was Six";
else
    s="It was something else, who knows?";

Это прекрасно скомпилируется, даже без инициализации s. Это работает в сложных случаях if / else, циклах и исключениях, так что не просто предполагайте, что он будет ловить только тривиальные случаи, подобные этому!

Таким образом, «Лучшая практика» - НИКОГДА не инициализировать переменные равными «», 0 или нулю. Не инициализируйте их, если это действительно не имеет смысла, и вы не используете значение, которое вы им задаете.

Как только вы получите ошибку в моем примере, вместо остального вы можете просто инициализировать s как "Это было что-то еще, кто знает?" вместо добавления else - это было бы совершенно правильно; но не устанавливая его в null или "" по привычке, по крайней мере, он мог напомнить вам, что вы должны были это сделать.

3 голосов
/ 06 марта 2009

Оставьте это поле пустым: private String mem;

Что касается «Что делать, если s равно нулю», то следует указать, что все объекты должны быть в допустимом состоянии. Но то, что является «действительным», полностью зависит от вашего приложения. Когда остальная часть вашей программы ссылается на mem и находит ее равной null, что произойдет? Было бы лучше иметь пустую строку или другое значение по умолчанию? Это зависит от обстоятельств.

3 голосов
/ 06 марта 2009

Короче говоря, нет лучшей практики.

Зависит от вашей модели. Некоторые строки могут быть обнуляемыми, а другие (обязательными) всегда должны содержать значение. Иногда больше, чем просто пустая строка.

Я бы не стал слепо выделять пустую строку для всего.

2 голосов
/ 06 марта 2009

Это зависит от использования этого атрибута.

Является ли значение NULL допустимым в вашей программе?

Если это не так, вы должны проверить его и бросить Npe.

A ( int a, String s  ) { 
    if( s == null ) { 
        throw new NullPointerException("The value of s cannot be null"); 
    }
    ....
}

Если это допустимое значение, то проблем не будет.

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

1 голос
/ 06 марта 2009

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

class A {
   private final String mem;
   private int num;
   A (int a) {
      this.num = a; // <= compile error, mem must be assigned
   }
   A (int a, String s) {
       this.num = a;
       this.mem  = s; // <= you need to null-check yourself
   }
}

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

Возможно, будущее принесет аннотацию @NotNull ...

1 голос
/ 06 марта 2009

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

0 голосов
/ 06 марта 2009

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

Во всех случаях ваш конструктор должен выбросить NullPointerException или IllegalArgumentException, если в него передана неверная строка.

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