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

Java 调试变量时遇到问题可能未初始化错误,java,Java,我在档案中看到了很多类似的问题,但我找不到像我遇到的问题这样的场景 下面是我的代码。“finalPrice”和“grandTotalPrice”可能未初始化,我遇到了错误。代码行在程序的末尾 应通过控制台输入从上面为变量分配总计。我不确定错误是什么,或者为什么。谁能帮我解释一下吗 代码: 若框架的类型不是R、R、F或F,会发生什么? 一种可能的解决方案是在交换机中添加一个“默认”案例 我认为这段代码更接近您想要的(我减少了很多重复)。请注意,我并没有真正处理错误(对isValidChoice和i

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

下面是我的代码。“finalPrice”和“grandTotalPrice”可能未初始化,我遇到了错误。代码行在程序的末尾

应通过控制台输入从上面为变量分配总计。我不确定错误是什么,或者为什么。谁能帮我解释一下吗

代码:


若框架的类型不是R、R、F或F,会发生什么? 一种可能的解决方案是在交换机中添加一个“默认”案例

我认为这段代码更接近您想要的(我减少了很多重复)。请注意,我并没有真正处理错误(对isValidChoice和isFrameType方法的调用是如何处理它们的开始)。上面的问题是,您基本上假设用户只会输入有效的输入,而忘记了有时,即使Y和N是他们可以在Q中输入的唯一有效选项。我还修复了一个错误,您不总是打印总计,也没有设置总计(打印F上方的最后一部分)

我的最后一个建议是不要使用双精度(除非你的导师告诉你),因为它们在某些情况下会给你不准确的数字

class Main
{
    static Scanner console = new Scanner(System.in);    
    static final double REGULAR_FRAME = .15;
    static final double FANCY_FRAME = .25;
    static final double COLOR = .10;
    static final double CARDBOARD = .02;
    static final double GLASS = .07;
    static final double CROWNS = .35;

    public static void main (String[] args)
    {   
        final double length;
        final double width;
        final char   typeOfFrame;
        final char   choiceOfColor;

        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);

        if(!(isFrameType(typeOfFrame)))
        {

        }
        else
        {
            final double area;
            final double perimeter; 
            final double priceOfFrame;
            final double priceOfCardboard;
            final double priceOfGlass;

            area             = (length * width);
            perimeter        = (2 * length) + (2 * width);
            priceOfFrame     = (perimeter * REGULAR_FRAME);
            priceOfCardboard = (area * CARDBOARD);
            priceOfGlass     = (area * GLASS);  

            if(isValidChoice(choiceOfColor))
            {
                final double priceOfColor;
                final double finalPrice;
                final char   choiceOfCrowns;
                final double grandTotalPrice; 

                if(choiceOfColor == 'N')
                {
                    finalPrice = (priceOfFrame + priceOfCardboard + priceOfGlass);
                }
                else
                {
                    priceOfColor = (area * COLOR);          
                    finalPrice   = (priceOfFrame + priceOfColor + priceOfCardboard + priceOfGlass);     
                }    

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

                if(isValidChoice(choiceOfCrowns))
                {
                    if(choiceOfCrowns == 'Y')
                    {
                        final double crownFinalPrice;
                        final int    numberOfCrowns;

                        System.out.println ("How many crowns would you like? ");    
                        numberOfCrowns  = console.nextInt();        
                        crownFinalPrice =(numberOfCrowns * CROWNS);
                        grandTotalPrice = (crownFinalPrice + finalPrice);
                    }   
                    else
                    {
                        grandTotalPrice = finalPrice;
                    }

                    System.out.printf ("Your total comes to: $%.2f%n", grandTotalPrice);    
                }
            }
        }
    }   

    private static boolean isFrameType(final char c)
    {        
        final char lower;

        lower = Character.toLowerCase(c);

        return (lower == 'r' || lower == 'f');
    }

    private static boolean isValidChoice(final char c)
    {
        return (c == 'Y' || c == 'N');
    }
}

之所以发生这种情况,是因为编译器警告您,在应用程序的某些运行期间可能从未设置过这些值。这些值是在
开关
if
语句中设置的,但编译器警告您,某些输入可能导致这些值未初始化

定义它们时,只需将它们设置为一个值即可:

double finalPrice = 0, grandTotalPrice = 0; 

但您也可以确保,无论应用程序采用何种路径,都可以设置它们(无论如何,了解所有可能的路径是一种良好的做法)。

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

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

  • main()
    方法太长并且包含太多内容。我展示的重构是“下一步”的一个很好例子这并不是一个完整的过程……但首先要做的是将一些逻辑提取到一个可消化的子集中。软件构建依赖于将东西分解成可以推理的组件,为什么不从框架价格计算机开始呢

  • 与前一点相关,您需要努力将变量范围缩小到绝对可能的最窄范围。局部性是您的朋友。最小化变量范围。这有助于将事物分解为单独的方法,但也适用于将变量放入块等。还有一个问题。第45项:最小化变量范围局部变量的范围

  • 这是一个有争议的例子,但我会提供我的观点。在任何地方都可以使用
    final
    。在大多数情况下,可变性不是你的朋友,而这段代码就是一个很好的例子——你有很多不同地方的比特和碎片,而事实上,大多数值都可以被定义一次,并且是绝对的,而另一个则可以计算可以线性进行。它更具可读性/可维护性,在编译阶段而不是在迭代调试中发现的逻辑错误数量会让您感到惊讶。支持不变性,明智地允许可变性,并且只有在有原因的情况下。有关讨论和几个相关的链接,请参阅第15项:最小化易变性

  • 更喜欢
    enum
    而不是
    String
    char
    或其他任何东西。特别是在处理来自用户或外部系统的潜在错误输入时,您的首要目标应该是将状态空间减少到绝对最小,并将内容放入受控词汇表中。我在这里做了第一步,但是您的代码应该向用户抛出异常或发出错误消息(取决于抽象级别;此处发出错误并再次请求输入)尽可能靠近接口,不允许非结构化/脏数据传播到应用程序中的深度超过必要的程度。非结构化/脏数据传播的深度越深,您拥有的上下文就越少,处理故障的逻辑就变得越丑陋/混乱。然后,您增加了错误处理逻辑,使得死气沉沉的简单内部计算变得不稳定。

  • 重复是一种代码气味。如果您在两个不同的位置计算区域,请重构它以避免。与此相关:,但像区域=长度x宽度这样简单的事情的重复阈值正好是一次。最小化或消除重复代码。

  • 在异常情况下使用
    Exception
    。这实际上结束了我的第一点和你的问题的循环。你的代码中有一些变量,编译器不确定这些变量是否正在初始化,因为在异常情况下没有为它们定义好的初始化值——它们代表了erroneous输入,不是要挤压的编译器警告。控制状态空间,当遇到意外状态时,抛出异常。与无提示但不正确的结果相比,显式、可解释且可能可恢复的错误更好

那里
double finalPrice = 0, grandTotalPrice = 0; 
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);
  }
}