3

我一直在研究我的一些 AP cs 项目,并想知道这样做之间的区别:

public class CalculateTaxes {
private Scanner in; 

public CalculateTaxes(){
    in = new Scanner(System.in);
}

}

和这个:

public class CalculateTaxes {
 private Scanner in = new Scanner(System.in); 

 public CalculateTaxes(){

 }

}

我见过很多例子,他们在一行中声明一个对象并在代码的其他地方实例化它。为什么不在同一行声明和实例化一个对象呢?

4

3 回答 3

2

让我们测试如何编译这些类。

public class Test1 {
    private Scanner in;

    public Test1() {
        in = new Scanner(System.in);
    }
}

public class Test2 {
    private Scanner in = new Scanner(System.in);

    public Test2() {

    }
}

如果我们使用javap -c Test1我们会看到

Compiled from "Test1.java"
public class Test1 {
  public Test1();
    Code:
       0: aload_0       
       1: invokespecial #10                 // Method java/lang/Object."<init>":()V
       4: aload_0       
       5: new           #12                 // class java/util/Scanner
       8: dup           
       9: getstatic     #14                 // Field java/lang/System.in:Ljava/io/InputStream;
      12: invokespecial #19                 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
      15: putfield      #22                 // Field in:Ljava/util/Scanner;
      18: return        
}

如果我们使用它,Test2我们会得到

Compiled from "Test2.java"
public class Test2 {
  public Test2();
    Code:
       0: aload_0       
       1: invokespecial #10                 // Method java/lang/Object."<init>":()V
       4: aload_0       
       5: new           #12                 // class java/util/Scanner
       8: dup           
       9: getstatic     #14                 // Field java/lang/System.in:Ljava/io/InputStream;
      12: invokespecial #19                 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
      15: putfield      #22                 // Field in:Ljava/util/Scanner;
      18: return        
}

所以你可以看到类中in字段的初始化是Test2在构造函数开始时由编译器自动移动的。

事实上,这段代码将在该类的每个构造函数的开始处移动(super()如果有的话,在调用之后立即移动),所以唯一的区别是,如果你的构造函数很少,你可以in在构造函数之外的一个地方初始化字段,而不是在每个构造函数中都这样做.

但是,如果假设您想根据构造函数中传递的某些参数来初始化字段,那么您必须在构造函数块中进行。

于 2013-10-18T16:38:14.710 回答
0

如果您打算在一个范围内为对象分配一个值,但需要它在另一个范围内可见,则拆分声明和分配可能很有用。

伪代码:

{ 
  // Outer loop
  SomeObject a;
  if (condition_one == condition_two)
      a = new SomeObject(4);
  else
      a = new SomeObject(12);
  a.doStuff();
}

如果 a 仅在 if 语句中声明,则它在该循环之外将不可见。

{
  if (a == b)
      SomeObject a = new SomeObject(5);
  a.doStuff(); // ERROR
}
于 2013-10-18T16:29:28.617 回答
0

在这种情况下没有太大区别。在某些情况下,您可以根据构造函数中发送的参数使用不同的参数。

最终,在专业的编程环境中,你的目标不是“现在”最好的,而是当你需要重新阅读代码并理解为什么要做某事时,什么能帮助你理解 6 个月内发生的事情。您如何实现它将有助于记录意图。

于 2013-10-18T16:29:57.093 回答