2013-08-29 3 views
2

저는이 문제를 가지고 있습니다. 실제로 작동 했으므로 더 많은 쿼리가 있었지만 왜, 현재 자바를 배우고 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 변수는 해당 클래스의 모든 객체에서 사용할 수 있습니다. 그러므로 이들은 종종 '클래스 필드'라고 불리는 반면 비 정적 멤버 변수는 '객체 필드'라고합니다. 현재의 방법은 static 때문에 이것은 아마, 당신은 현재 calculatePrice 함수를 호출하는 방식으로 작동하지 않습니다

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

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

: 같은 클래스의 서명은, 잘 설계된 세계에 보일 것입니다.

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

재귀 호출을 catch하는 데 +1이 관련 설명과 함께 사용됩니다. – rgettman

+1

마음. 부푼. 덕분에 도움이되었습니다. 아직 루프 나 예외 처리를 사용하는 장이 아닙니다 : D while 루프와 for 루프를 사용하는 방법을 알고 있습니다. 아직 책을 가르치지 않아서 태스크를 수행 할 수 있다고 가정합니다. :) – Gibbo

5

변수는 로컬로 선언되므로이 메서드를 호출 할 때마다 0으로 초기화됩니다. 그런 다음 다음 번에 호출 될 때까지 범위를 벗어나 다시 0으로 초기화됩니다.

private static double totalBill = 0;이 메소드 외부에있는 경우 calculatePrice이 몇 번 호출 되더라도 값을 유지하는 static 클래스 변수입니다. 범위는 메서드뿐 아니라 전체 클래스이며 메서드가 호출 될 때 다시 초기화되지 않습니다.

+0

고마워요 !!! 이것은 실제로 내 기억을 뒤 흔들어서 총체적인 의미를 가지며, 당신의 도움에 감사드립니다. – Gibbo

+1

당신의 반응은 미묘하게 틀립니다 : OP의 구현에서'calculatePrice()'메소드는 스스로를 호출합니다. 그러므로 실제로 일어나고있는 것은'totalBill' 변수가 범위를 벗어나지 않고 가려져 있다는 것입니다. 물론이 경우에는 동작이 동일합니다. –

-1

정적 변수는 object 대신 클래스에 바인딩됩니다. 첫 번째 경우에는 객체에 대한 변수를 설정해야합니다.

관련 문제