调试变量时遇到问题可能没有初始化错误

bar*_*nes 5 java

我在档案中看到了很多类似的问题,但我找不到像我遇到的问题那样的场景.

以下是我的代码.我遇到了"finalPrice"错误,"grandTotalPrice"可能尚未初始化.代码行是在程序的最后.

应通过上面的控制台输入为变量分配总数.我不确定错误是什么,或者为什么.任何人都可以帮助我,解释一下吗?

码:

import java.util.*;


public class PictureFrames
{

    static Scanner console = new Scanner(System.in);

    static final double REGULAR_FRAME = .15, FANCY_FRAME = .25;
    static final double COLOR = .10, CARDBOARD = .02, GLASS = .07, CROWNS = .35;


    public static void main (String[] args)
    {

    double length, width, area, perimeter; 
    double priceOfFrame, priceOfColor, priceOfCardboard, priceOfGlass, priceOfCrowns, finalPrice, crownFinalPrice, grandTotalPrice; 
    int numberOfCrowns;
    char typeOfFrame, choiceOfColor, choiceOfCrowns;



    System.out.println ("Please enter the length of your picure in inches:");
    length = console.nextDouble();

    System.out.println ("Please enter the width of your picure in inches: ");
    width = console.nextDouble();

    System.out.println ("Please enter the type of frame: R or r (Regular), F or f (Fancy). ");  
    typeOfFrame = console.next().charAt(0);

    System.out.println ("Would you like to add color?: Y for (Yes), N for (No): "); 
    choiceOfColor = console.next().charAt(0);


    switch (typeOfFrame)
    {
    case 'R':
    case 'r':
        if (choiceOfColor == 'N')
        {
            area = (length * width);
            perimeter = (2 * length) + (2 * width);
            priceOfFrame = (perimeter * REGULAR_FRAME);
            priceOfCardboard = (area * CARDBOARD);
            priceOfGlass = (area * GLASS);
            finalPrice = (priceOfFrame + priceOfCardboard + priceOfGlass);
        break;
        }
        else if (choiceOfColor == 'Y')
        {
            area = (length * width);
            perimeter = (2 * length) + (2 * width);
            priceOfColor = (area * COLOR);          
            priceOfFrame = (perimeter * REGULAR_FRAME);
            priceOfCardboard = (area * CARDBOARD);
            priceOfGlass = (area * GLASS);      
            finalPrice = (priceOfFrame + priceOfColor + priceOfCardboard + priceOfGlass);       
        break;
        }
    case 'F':
    case 'f':
        if (choiceOfColor == 'N')
        {
            area = (length * width);
            perimeter = (2 * length) + (2 * width);
            priceOfFrame = (perimeter * FANCY_FRAME);
            priceOfCardboard = (area * CARDBOARD);
            priceOfGlass = (area * GLASS);
            finalPrice = (priceOfFrame + priceOfCardboard + priceOfGlass);
        break;
        }
        else if (choiceOfColor == 'Y')
        {
            area = (length * width);
            perimeter = (2 * length) + (2 * width);
            priceOfColor = (area * COLOR);          
            priceOfFrame = (perimeter * FANCY_FRAME);
            priceOfCardboard = (area * CARDBOARD);
            priceOfGlass = (area * GLASS);      
            finalPrice = (priceOfFrame + priceOfColor + priceOfCardboard + priceOfGlass);       
        break;
        }

}       

    System.out.println ("Would you like to add crowns? Enter Y (Yes), or N (No): ");    
    choiceOfCrowns = console.next().charAt(0);

    if (choiceOfCrowns == 'Y')
    {
        System.out.println ("How many crowns would you like? ");    
        numberOfCrowns = console.nextInt();     
        crownFinalPrice =(numberOfCrowns * CROWNS);
        grandTotalPrice = (crownFinalPrice + finalPrice);
    }   
    else if (choiceOfCrowns == 'N')
            System.out.printf ("Your total comes to: $%.2f%n", grandTotalPrice);    

    }   

}
Run Code Online (Sandbox Code Playgroud)

and*_*soj 4

这是对代码的第一次重构,解决了您的特定问题以及其他一些问题。重构中解决的一些观察结果:

  • 为了回答您的问题(以及其他一些答案),不要养成盲目初始化变量只是为了让编译器错误消失的习惯。这里的编译器错误表明您需要明确定义变量(对您的应用程序有意义),无论潜在状态如何。初始化变量只是隐藏了尚未处理的不受控制/意外状态的问题。

  • 方法main() 太长,内容太多。我展示的重构是“下一步”的一个很好的例子,绝不是一个完整的过程......但第一件事是将一些逻辑提取到一个可消化的子集中。软件构建依赖于将事物分解成您可以推理的组件,为什么不从您的框架价格计算机开始呢?

  • 与上一点相关,您需要努力将变量的范围缩小到绝对最窄的可能范围。本地化是你的朋友。 最小化变量范围。 这可以通过将事物分解为单独的方法来帮助,但它也适用于将变量放入块等。这是一个很好的相关 SO 讨论。另外,Effective Java Item 45:最小化局部变量的范围。

  • 这是一个有争议的问题,但我会提出我的看法。final可以在任何地方使用。在大多数情况下,可变性不是你的朋友,这段代码就是一个很好的例子——你在很多不同的地方都有一些零碎的值,而事实上大多数值都可以一次明确地定义,其他计算可以线性进行。它更具可读性/可维护性,并且您会惊讶地发现在编译阶段而不是在迭代调试中 发现的逻辑错误的数量。赞成不变性,明智地允许可变性,并且只有在有原因的情况下。 请参阅我对此问题的回答以进行一些讨论,以及几个相关的、链接的 SO 问题。另外,《Effective Java第 15 条:最小化可变性》。

  • enumString喜欢char或其他什么。特别是在处理来自用户或外部系统的潜在行为不当输入时,您的首要目标应该是将状态空间减少到绝对最小值,并将事物纳入受控词汇表中。我在这里进行了第一遍,但是您的代码应该抛出异常或向用户发出错误消息(取决于抽象级别;此处发出错误并再次要求输入)尽可能靠近接口,不允许非结构化/脏数据传播到应用程序中比必要的更深入。越深入,你拥有的上下文就越少,应对失败的逻辑就会变得越丑陋/越混乱。然后,您积累错误处理逻辑,使极其简单的内部计算变得不可测试。

  • 重复是一种代码味道。 如果您在两个不同的地方计算面积,请重构它以避免。与SO相关:“什么重复阈值......?” ,但是像面积 = 长度 x 宽度这样简单的东西的重复阈值恰好是一次。 最小化或消除重复代码。

  • 用于Exception特殊条件。这实际上结束了我的第一点和你的问题的循环。您的代码中包含编译器不确定是否已初始化的变量,因为在特殊情况下没有明确定义的值可供初始化 - 它们代表错误的输入,而不是编译器警告压缩。控制状态空间,当遇到意外状态时,抛出异常。一个明确的、可解释的、可能可恢复的错误比一个无声但不正确的结果更好。

还有更多,但我认为这是一组有用的批评,而且超出了您的要求。代码:

import java.util.*;

public final class PictureFrames
{

  static Scanner console = new Scanner(System.in);

  static final double REGULAR_FRAME = .15, FANCY_FRAME = .25;
  static final double COLOR = .10, CARDBOARD = .02, GLASS = .07, CROWNS = .35;

  enum FrameType {
    /** Regular. */
    R, 
    /** Fancy. */
    F;
  };


  static double areaPriceInDollars(final FrameType frameType,
                                   final double length,
                                   final double width,
                                   final boolean color)
  {
    final double area,perimeter,
      priceOfFrame,
      priceOfCardboard,
      priceOfGlass,
      priceOfColor;

      area = length * width;
      perimeter = 2 * (length + width);

      priceOfCardboard = (area * CARDBOARD);
      priceOfGlass = (area * GLASS);      

      if (color) 
        priceOfColor = area * COLOR;
      else 
        priceOfColor = 0.0;

      switch (frameType) {
        case R:
          priceOfFrame = (perimeter * REGULAR_FRAME);
          break;
        case F:
          priceOfFrame = (perimeter * FANCY_FRAME);
          break;
        default:
          throw new IllegalArgumentException("FrameType "+frameType+" unknown, no price available.");
      }

      return priceOfColor + priceOfCardboard + priceOfGlass + priceOfFrame;
    }       


  public static void main(String[] args)
  {
    System.out.println("Please enter the length of your picure in inches:");
    final double length = console.nextDouble();

    System.out.println("Please enter the width of your picure in inches: ");
    final double width = console.nextDouble();

    System.out
        .println("Please enter the type of frame: R or r (Regular), F or f (Fancy). ");
    final char typeOfFrame = console.next().charAt(0);
    FrameType frameType = FrameType.valueOf(""
        + Character.toUpperCase(typeOfFrame));

    System.out
        .println("Would you like to add color?: Y for (Yes), N for (No): ");
    final char choiceOfColor = console.next().charAt(0);
    final boolean color = Character.toUpperCase(choiceOfColor) == 'Y';

    System.out
        .println("Would you like to add crowns? Enter Y (Yes), or N (No): ");
    final char choiceOfCrowns = console.next().charAt(0);
    final boolean crowns = Character.toUpperCase(choiceOfCrowns) == 'Y';

    final double priceOfCrowns;
    if (crowns) {
      System.out.println("How many crowns would you like? ");
      final int numberOfCrowns = console.nextInt();
      priceOfCrowns = (numberOfCrowns * CROWNS);
    } else {
      priceOfCrowns = 0.0;
    }

    final double grandTotalPrice = priceOfCrowns
        + areaPriceInDollars(frameType, length, width, color);
    System.out.printf("Your total comes to: $%.2f%n", grandTotalPrice);
  }
}
Run Code Online (Sandbox Code Playgroud)