我一直在研究我的一些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(){
}
}
我见过许多例子,他们在一行中声明了一个对象,并在代码中的其他地方实例化它。为什么不在同一行中声明和实例化一个对象?
答案 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个月内发生的事情。你如何实施它将有助于记录意图。