2

在java中创建对象(或任何东西)时,做的有什么区别,例如,

Dog d = new Dog();

而不是做

Dog d;

然后稍后,用

d = new Dog();

第一个不是更简单更容易吗?为什么人们会采用第二种方式?

4

11 回答 11

5

想想下面的场景。假设的构造函数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();
于 2012-01-20T22:16:02.643 回答
3

这个问题缺乏一些重要的背景。如果变量定义和使用在不同的范围内,则存在很大差异。例如:

class A { 
  Dog d;

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

...允许 Dog 的每个成员都可以访问class A.

如果使用在同一范围内,

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

...那么这是一个可读性问题,因为代码将在一两行中运行相同的代码。

于 2012-01-20T22:17:06.483 回答
1

因为你在声明对象时并不总是知道如何构造它。例如:

Dog dog;
if ("M".equals(sex)) {
    dog = new Dog("Medor");
}
else {
    dog = new Dog("Mirza");
}
dog.walk();
于 2012-01-20T22:17:47.100 回答
1

很多原因。一个原因可能是初始化取决于运行时确定的条件。例如,

Animal pet;
...
if(input == 0) pet = new Dog();
else pet = new Cat();
...
pet.sleep();
于 2012-01-20T22:18:31.717 回答
1

这只是声明一个引用(你说d会有 type Dog):

Dog d;

这是创建一个新对象,并将其分配给引用变量d

new Dog();

您可以将它结合起来,因为您经常两者都做,但并非总是如此。

于 2012-01-20T22:20:23.520 回答
1

虽然习惯性地将声明和初始化分开并不是一个好主意

  • 在某些情况下您要这样做(参见 try catch 示例),

  • 在某些情况下,它可以提高代码的可读性(参见 Max Schmidt 的示例),

  • 在某些情况下,它会使您的代码更加健壮。

为了说明最后一点,考虑修改 Max Schmidt 的示例:

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

看到错误了吗?如果input既不是"lab"or "bull",当我们null遛狗时,代码就会死掉。

但是,如果我们删除 的初始化d,那么编译器会告诉我们有一条通过代码的路径d未初始化。如果我们注意,我们会在代码运行之前看到错误并修复它。

于 2012-01-20T23:22:04.327 回答
0

这是延迟初始化的粗略示例。在您的程序中,您可能永远不需要 Dog 对象的实际实例。在这些情况下,您可以简单地声明 Dog 引用,它不会消耗太多内存,然后在需要时对其进行初始化。

于 2012-01-20T22:16:20.950 回答
0

对象创建和对象声明。你可以在这里阅读

当您这样做时Dog d = new Dog();,您正在声明一个d类型的变量,Dog并使用new运算符创建变量。

因此,您通常会在开始时声明您需要的变量,并仅在真正使用它们时创建它们。

于 2012-01-20T22:16:24.653 回答
0

没有理由,这只是一种糟糕的编码习惯。由于在初始化之前不能使用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();
于 2012-01-20T22:16:27.003 回答
0

在您有类似 try/catch 之类的东西将创建 Dog 的情况下,第二个可能更有用,创建 dog 实例不应停止该方法中的其他逻辑。如果你想在 try/catch 之后使用 dog 实例,否则继续你的逻辑。

如果在 try/catch 中使用第一个语法,则不能在外部使用它。

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

}

d.methodCall();
于 2012-01-20T22:16:47.163 回答
0

有时除了第二种方法之外别无他法,例如,如果狗是拉布拉多犬和斗牛犬的超类:

Dog d;

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

d.urinate():
于 2012-01-20T22:20:08.467 回答