Java: при объявлении объектов или целых - PullRequest
2 голосов
/ 21 января 2012

При создании объекта (или чего-либо) в Java, в чем разница между выполнением, например,

Dog d = new Dog();

вместо выполнения

Dog d;

, а затем завершениемэто (иногда внутри и в начале метода) с

d = new Dog();

Разве первый не был бы более простым и легким?Почему люди делают это вторым способом?

Ответы [ 11 ]

5 голосов
/ 21 января 2012

Подумайте о следующем сценарии.Предположим, что конструктор Dog может выдать исключение:

try {
    Dog d = new Dog();    
} catch(Exception ex) {
    // treat exception
}

d.bark();

Это не скомпилируется, поскольку d не виден вне блока tryЧто вам нужно сделать, это:

Dog d = null;
try {
    d = new Dog();    
} catch(Exception ex) {
    // treat exception
}
if(d != null) d.bark();

И есть много других подобных ситуаций.Например, у вас может быть блок if-else, где d инициализируется по-разному в зависимости от некоторого условия:

Dog d = null;
if(/* condition */)
    d = new Dog("Lassie");   
} else {
    d = new Dog("Sam");
}
d.bark();
3 голосов
/ 21 января 2012

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

class A { 
  Dog d;

  void foo() { d = new Dog(); }
}

... позволяет собаке быть доступным каждому члену class A.

Если использование находится в той же области,

class A {
  void foo() {
     Dog d;
     d = new Dog();
  }
}

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

1 голос
/ 21 января 2012

Хотя не стоит привычно разделять объявление и инициализацию

  • В некоторых случаях требуется для этого (см. Пример try catch),

  • В некоторых случаях это улучшает читаемость кода (см. Пример Макса Шмидта),

  • В некоторых случаях это делает ваш код более надежным.

Чтобы проиллюстрировать последний пункт, рассмотрим измененный пример Макса Шмидта:

Dog d = null;
if (input.equals("lab")) {
   d = new Labrador();
} else if (input.equals("bull")) {
   d = new Bulldog();
}
d.walk();

Видишь ошибку? Если input не является ни "lab", ни "bull", код умрет, когда мы выгуливаем null собаку.

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

1 голос
/ 21 января 2012

Это всего лишь объявление ссылка (вы говорите, d будет иметь тип Dog):

Dog d;

Это создание нового объекта и присвоение его ссылочной переменной d:

new Dog();

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

1 голос
/ 21 января 2012

Множество причин.Одной из причин может быть то, что инициализация зависит от условий, определенных во время выполнения.Например,

Animal pet;
...
if(input == 0) pet = new Dog();
else pet = new Cat();
...
pet.sleep();
1 голос
/ 21 января 2012

Потому что вы не всегда знаете, как создать объект, когда объявляете его.Например:

Dog dog;
if ("M".equals(sex)) {
    dog = new Dog("Medor");
}
else {
    dog = new Dog("Mirza");
}
dog.walk();
0 голосов
/ 21 января 2012

Иногда нет другого пути, кроме второго, например, если собака является суперклассом Лабрадора и Бульдога:

Dog d;

if (input == "lab"){
  d = new Labrador();
}else if {
 d = new  Bulldog();
}

d.urinate():
0 голосов
/ 21 января 2012

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

Если вы используете первый синтаксис внутри try / catch, вы не можете использовать его снаружи.

try {
    Dog d = new Dog();    
} catch(Exception ex) {

}

d.methodCall();
0 голосов
/ 21 января 2012

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

Dog d;
//...you cannot use `d` in any way! It won't compile
d = new Dog();
//now you can

Это однако:

Dog d = null;
//...
d = new Dog();

имеет смысл, поскольку кто-то может проверить null (ленивая инициализация и т. Д.)

Ради простоты вы должны предпочесть:

final Dog d = new Dog();
0 голосов
/ 21 января 2012

Создание объекта и объявление объекта. Вы можете прочитать об этом здесь

Когда вы делаете Dog d = new Dog();, вы объявляете переменную d типа Dog и, используя оператор new, создаете переменную.

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

...