2013-08-29 24 views
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; 

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

+0

这是关于范围。 –

+0

对,我需要回到那一章。我认为只要它在同一个街区就可以。不过谢谢!我至少可以回头重读:D – Gibbo

回答

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

+1

+1用于捕获递归调用,并附带相关说明。 – rgettman

+1

介意。吹。这有助于很多,谢谢!我不在使用循环或异常处理的章节中:D我知道如何使用while和for循环,我只是假设你可以在没有使用它们的情况下完成任务,因为本书还没有教授它们:) – Gibbo

5

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

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

+0

谢谢!这真的慢跑我的记忆,并使总体感,感谢您的帮助:) – Gibbo

+1

你的回应是微妙的错误:在OP的实现中,'calculatePrice()'方法调用自己。因此,实际发生的情况是'totalBill'变量被屏蔽,不会超出范围。当然,这种情况下的行为是一样的。 –

-1

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