我在档案中看到了很多类似的问题,但我找不到像我遇到的问题那样的场景.
以下是我的代码.我遇到了"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)
这是对代码的第一次重构,解决了您的特定问题以及其他一些问题。重构中解决的一些观察结果:
为了回答您的问题(以及其他一些答案),不要养成盲目初始化变量只是为了让编译器错误消失的习惯。这里的编译器错误表明您需要明确定义变量(对您的应用程序有意义),无论潜在状态如何。初始化变量只是隐藏了尚未处理的不受控制/意外状态的问题。
方法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)