2

私はこの問題を抱えています。実際に機能するようになったので、より多くのクエリが発生しましたが、理由がわかりません。現在、Java を学習し、cengage の第 7 版を読んでいます。これは演習の 1 つです。

だから私はこの方法を持っています:

public static void calculatePrice(){
        Scanner userInput = new Scanner(System.in);
        int orderNumber;
        double totalBill = 0;

        orderNumber = userInput.nextInt();
        switch(orderNumber){
        case 1:
            totalBill = totalBill + American;
            displayMenu();
            calculatePrice();
            break;
        case 2:
            totalBill = totalBill + Espresso;
            displayMenu();
            calculatePrice();
            break;
        case 3:
            totalBill = totalBill + Latte;
            displayMenu();
            calculatePrice();
            break;
        case 0:
            System.out.println("Your total bill will be $"+ totalBill);
            break;
        }
    }

この章は意思決定について教えてくれるので、この場合はスイッチを使用することにしました。ユーザーに質問する別の方法があります。

この方法に関する私の問題はフィールドです:

double totalBill = 0;

これは機能せず、理由がわかりません。プログラムはコンパイルされますが、ケース シナリオ内のロジックに関係なく、常に設定価格 0 が返されます。

ただし、メソッドからそのフィールドを削除して上部に配置すると、クラス全体になります。

private static double totalBill = 0;

正常に動作しますが、これはなぜですか? 他のメソッドで使用する必要がないため、メソッド内で使用する方が賢明に思えました。

4

3 に答える 3

5

変数totalBillはローカルで宣言されるため、このメソッドが呼び出されるたびに 0 に初期化されます。その後、次に呼び出されるまで範囲外になり、0再び初期化されます。

private static double totalBill = 0;メソッドの外側では、何回呼び出されても値を保持するクラス変数staticになりました。calculatePriceスコープはメソッドだけでなくクラス全体であり、メソッドが呼び出されたときに再初期化されません。

于 2013-08-29T20:40:56.787 に答える
3
//Note that you declare this method static: as such it will have no access to object
//member fields, only to class fields: these are member fields declared 'static'
public static void calculatePrice(){
    Scanner userInput = new Scanner(System.in);//Note this has little to do with actually calculating price.
    int orderNumber;
    double totalBill = 0;//You a declaring a new variable that will disappear once it goes out of the scope of this method

    orderNumber = userInput.nextInt();
    switch(orderNumber){
    case 1:
        totalBill = totalBill + American;
        displayMenu();
        calculatePrice();//Recursive call!
        break;
//... eliding for brevity
    case 0:
        System.out.println("Your total bill will be $"+ totalBill);
        break;
    }
} //this is the point where all method variables go out of scope, because this 'stack frame' is unloaded. Any subsequent call to this method will not 'remember' any state that was not saved elsewhere.

したがって、再帰呼び出しを行っていることに注意してください。これが意味することは、関数に再び入るということです。「totalBill」変数は新しくインスタンス化され、他のすべての「totalBill」変数がマスクされます。これらの変数はまだ存在しています...下位のスタック フレームではアクセスできません。スタック フレームは、関数が実行される新しいテーブルと考えてください。新しい関数を呼び出すと、新しいテーブルが一番上に配置されます...しかし、一番上のテーブルしか見えません。他のすべてのテーブルはその下にあります。

変数 static を宣言することは、この型のすべてのオブジェクトのすべての関数が同じメモリ空間にアクセスできるように、変数を脇に置くことを意味します。static変数は、そのクラスのすべてのオブジェクトで使用できます。したがって、これらは「クラス フィールド」と呼ばれることが多く、非静的メンバー変数は「オブジェクト フィールド」と呼ばれます。クラス署名は、適切に設計された世界では次のようになります。

public class RegisterOrder {
  public double totalBill;//Available to only ONE instance (object) of this class.

  public void calculatePrice() {//note no 'static' modifier!
    //some code
  }
}

現在の方法はstatic. それを次のように変更する必要があります。

RegisterOrder order = new RegisterOrder();
order.calculatePrice();

また、再帰呼び出しは、非常に多くの注文を注文すると、プログラムがクラッシュすることを意味することに注意してください。これは、テーブルの積み上げが高すぎると考えてください。現代のシステムではこれを行うのは困難ですが (大量のメモリ)、適切な設計には次のループが必要です。

public function getOrder() {
  //instantiate variables

  orderNumber = userInput.nextInt();
  while (orderNumber != 0) {
    switch(orderNumber){
      case 1:
        totalBill = totalBill + American;
        break;
      case 2:
        totalBill = totalBill + Expresso;
        break;
      case 3:
        totalBill = totalBill + Latte;
        break;
      default:
        //Error handling is important!
        break;
     }
     displayMenu();
     orderNumber = userInput.nextInt();
  }
  System.out.println("Your total bill will be $"+ totalBill);
}

このバージョンでは、入力関数を再呼び出ししていないことに注意してください。また、この関数内で宣言された「totalBill」変数は、この関数の別の呼び出しによってアンロードまたはマスクされないことに注意してください。真にクリーンなコードでは、入力を取得するメソッドを請求書を計算するメソッドから分離しますが、手順は簡単です。:)

于 2013-08-29T20:54:21.573 に答える
-1

静的変数は、オブジェクトではなくクラスにバインドされます。最初のケースでは、オブジェクトの変数を設定する必要があります。

于 2013-08-29T20:41:49.953 に答える