什么时候申报对象?

时间:2013-10-18 16:25:50

标签: java object declaration

我一直在研究我的一些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(){

 }

}

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

3 个答案:

答案 0 :(得分: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字段在构造函数之外的一个地方而不是在每个构造函数中都这样做。

但是,如果我们想要根据构造函数中传递的某些参数初始化字段,那么你必须在构造函数块中执行它。

答案 1 :(得分: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
}

答案 2 :(得分:0)

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

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