字段在方法内不起作用

时间:2013-08-29 20:38:01

标签: java

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

所以我有这个方法:

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;

它运作正常,这是为什么?在方法中使用它似乎更聪明,因为没有其他方法需要使用它。

3 个答案:

答案 0 :(得分:5)

您的totalBill变量在本地声明,因此每次调用此方法时它都会初始化为0。然后它会超出范围,直到下次被调用,再次被初始化为0

在方法之外使用private static double totalBill = 0;,现在它是一个static类变量,无论调用calculatePrice多少次,它都会保留其值。范围是整个类,而不仅仅是方法,并且在调用方法时不会重新初始化。

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

这可能不适用于您当前调用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'变量永远不会被另一个对此函数的调用卸载或屏蔽。在真正干净的代码中,您将输入获取方法与账单计算方法分开,但是小步骤。 :)

答案 2 :(得分:-1)

静态变量绑定到类而不是对象。在第一种情况下,您必须为对象设置变量。