правильный способ инициализации переменных - PullRequest
1 голос
/ 26 апреля 2010

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

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

variables here
{
  private Jlist contactList;
  String [] contactArray;
  ArrayList <String> contactArrayList;
  ResultSet namesList


// constructor here

public whatever()
{
    GridLayout aGrid = new GridLayout(2,2,10,10);

    contact1 =  new String();
    contact2 =  new String();
    contact3 =  new String();

    contactArrayList = new ArrayList<String>();

// is something supposed too go in the () of this JList?
   contactList = new JList();

   contactArray = new String[5];

   from1 =new JLabel ("From: " + contactArray[1]);



gridlayout.add(components)// theres too many components to write onto SO.

}


// methods here

public void fillContactsGui()
{
    createConnection();
ArrayList<String> contactsArrayList = new ArrayList<String>();

    while (namesList.next())
    {
        contactArrayList.add(namesList.getString(1));
        ContactArray[1] = namesList[1];
    }
}

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

p.s. извините за грязный пример кода. я сделал все возможное.


Ладно, здесь немного яснее.

Общая схема кода - это то, о чем я спрашиваю.

мой код отформатирован следующим образом.

переменные; конструктор; методы;

Буду ли я прав, говоря, что это должно выглядеть так

 public class test
{
  int i;

  public test()
  {
    i = 0;
 }

  public void addi()
  {
   i = i +1;
  }
}

и не так

public class test
{
  int i = 0;

  public test()
  {
   int i = 0;
  }


  public void addi()
  {
    int i = i +1;
  }
}

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

Ответы [ 5 ]

2 голосов
/ 26 апреля 2010

Переменные могут быть инициализированы в разных местах по разным причинам. Например, в вашем примере кода вы всегда инициализируете свой список контактов новым JList. Это можно сделать в разделе «переменные здесь» как private JList contactList = new JList().

Ваш contactArrayList выглядит так, как будто он обычно основан на параметрах, передаваемых в конструктор, поэтому элементы должны быть добавлены к нему в конструкторе. Если вы выбрали такой подход, то contactArrayList должен быть объявлен как final. Это заставит все конструкторы инициализировать список. (Если вы не хотите объявлять его окончательным, вы можете инициализировать его во время объявления таким же образом, как обрабатывался contactList.)

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

1 голос
/ 26 апреля 2010

Ответы на многие ваши вопросы приведены в этом уроке по Инициализация объекта в Java .

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

Вот еще несколько достойных ресурсов:

1 голос
/ 26 апреля 2010

Обычно вы должны инициализировать переменные как можно скорее, когда известно начальное значение. Вместо

ArrayList<String> contactArrayList;

рассмотрим это

static final int INITIAL_LIST_SIZE = 100;
List<String> contactArrayList = new ArrayList<String>(INITIAL_LIST_SIZE);

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

Приложение: обычно не одобряется для дублирования инициализаций по умолчанию. В последующем примере инициализация по умолчанию устанавливает i на ноль.

Ошибка: обратите внимание на исправленный комментарий относительно int i = 0 в конструкторе test, который скрывает поле i .

public class test {

    int i = 0; // superfluous, "int i;" is enough 

    public test() {
        int i = 0; // hides field i
    }

    public void addi() {
        int i = i + 1; // hides field i; won't increment field i
    }
}
1 голос
/ 26 апреля 2010

единственная проблема с неинициализацией - вы оставляете себя открытым для исключений нулевого указателя. в идеале вы должны инициализировать все, что вам нужно, в вашем конструкторе, чтобы вы могли быть уверены, что у любого другого метода есть с чем работать. альтернатива состоит в том, чтобы проверить, являются ли вещи нулевыми, прежде чем вызывать методы для них (например, if (list != null && list.size() > 0))

0 голосов
/ 26 апреля 2010

Ваш последний пример - тот, что с "public test () {int i = 0;}", вероятно, не будет работать как задумано. Перераспределив переменную «int» в test и addi, теперь у вас есть три переменные с именем «i»: переменная-член, определенная вверху, локальная переменная в test и другая локальная переменная в addi. Значение члена не изменяется ни одной из функций.

Я бы определенно избегал инициализации переменных фиктивными значениями, такими как ваш "contact1 = new String ()". Да, это предотвращает получение ошибки компиляции для неинициализированных переменных или, возможно, выдачи исключения нулевого указателя. Но если вы получите ошибку без этого, то это должно означать, что вы не смогли поместить реальное значение в переменную. Установка фиктивного значения не решает проблему, она просто скрывает ее. Это как наклеить ленту на сигнальную лампу на приборной панели: да, вы больше не видите предупреждение, но это не потому, что проблема устранена, а только потому, что вы ее скрыли.

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

Кроме того, я не уверен, что сказать о вашем примере. Я не уверен, что вы пытаетесь достичь. У вас есть переменные с именами contact1, contact2 и contact3, которые, кажется, никогда не используются. contactArray, по-видимому, должен быть заполнен fillContactsGui, но я не вижу, где он когда-либо вызывался. Я не уверен, являются ли это недостатками вашей логики или это просто неполный пример.

Что касается общего правильного способа инициализации и использования данных:

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

public void foobar()
{
  ... do some stuff ...
  int i=0;
  ... do other stuff ...
  i=i+j;
  ... etc ...
}

Я бы избегал его определения, а затем, если это возможно, позже инициализировал бы его, потому что это создает вероятность того, что вы не сможете его инициализировать. Конечно, если его можно инициализировать двумя различными способами, этого трудно избежать. Как:

public void foobar()
{
  int i;
  if (plugh>0)
    i=plugh;
  ... bunch more logic ...
  // Inside some IF so we won't even get here if i was set earlier
  if (zork==true)
    i=shambar;
  ... etc ...
}

Тем не менее, чем больше вы можете держать это вместе, тем лучше.

...