Java 字段不在方法内工作

Java 字段不在方法内工作,java,Java,我有这个问题,其实更多的是一个问题,因为我确实让它工作了,但我不明白为什么,我目前正在学习java并阅读cengage第七版,这是其中一个练习 所以我有这个方法: public static void calculatePrice(){ Scanner userInput = new Scanner(System.in); int orderNumber; double totalBill = 0; orderNumber = u

我有这个问题,其实更多的是一个问题,因为我确实让它工作了,但我不明白为什么,我目前正在学习java并阅读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;

它很好用,这是为什么?在方法内部使用它似乎更明智,因为没有其他方法需要使用它。

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


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

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

//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函数的方式不兼容,因为您当前的方法是静态的。您必须将其更改为:

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”变量永远不会被另一个调用卸载或屏蔽。在真正干净的代码中,您可以将输入获取方法与账单计算方法分开,但步骤很小。:)

这都是关于范围的。好吧,我需要回到那一章。我想只要它在同一个街区就可以了。不过谢谢!我至少可以回去重读一遍:谢谢!!!这真的让我记忆犹新,完全有道理,谢谢你的帮助:)你的回答是微妙的错误:在OP的实现中,
calculatePrice()
方法调用自己。因此,实际发生的是
totalBill
变量被屏蔽,而不是超出范围。当然,在本例中的行为是相同的。+1用于捕获递归调用,并带有相关的解释。Mind。吹。这很有帮助,谢谢!我还没有进入使用循环或异常处理的章节:D我知道如何使用while和for循环,我只是假设你可以在没有它们的情况下完成任务,因为这本书还没有教它们:)