2

我有这个问题,更多的是一个查询,因为我实际上让它工作了,但我不明白为什么,我目前正在学习 java 并阅读 cengage 第 7 版,这是练习之一。

所以我有这个方法:

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变量可用于该类的所有对象;因此它们通常被称为“类字段”,而非静态成员变量被称为“对象字段”。在精心设计的世界中,您的类签名应该如下所示:

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

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

这可能不适用于您当前调用 calculatePrice 函数的方式,因为您当前的方法是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 回答