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(){

 }

}

オブジェクトを 1 行で宣言し、コード内の別の場所でインスタンス化する例を数多く見てきました。同じ行でオブジェクトを宣言してインスタンス化しないのはなぜですか?

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コンストラクターのすべてで行うのではなく、コンストラクターの外側の 1 つの場所でフィールドを初期化できることです。 .

ただし、コンストラクターに渡された引数に応じてフィールドを初期化したい場合は、コンストラクター ブロックでそれを行う必要があります。

于 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 に答える