gpt4 book ai didi

java - 如何避免 'the local variable may not have been initialized' ?

转载 作者:搜寻专家 更新时间:2023-11-01 00:59:18 25 4
gpt4 key购买 nike

/*This is a program that calculates Internet advertising rates based on what features/options you choose.
*
*
*/

import java.util.Scanner;

public class InternetAdvertising
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);

int numberOfWords;

//I assigned 0 values to both as Eclipse suggested
float textCost = 0;
float linkCost = 0;

float graphicCost;

//<=25 words is a flat fee of $.40 per word plus Base fee of $3.00
final float TEXT_FLAT_FEE = 0.40F;
final float TEXT_BASE_FEE = 3.00F;

//<=35 words is $.40 for the first 25 words and
//an additional $.35 per word up to and including 35 words plus Base fee of $3.00
final float LESS_OR_EQUAL_THAN_THIRTYFIVE = 0.35F;

//Over 35 words is a flat fee of $.32 per word with no base fee
final float MORE_THAN_THIRTYFIVE = 0.32F;


System.out.println("Welcome!");

System.out.print("Enter the number of words in your ad: ");
numberOfWords = in.nextInt();

if (numberOfWords <= 25)
{
textCost = TEXT_BASE_FEE + (TEXT_FLAT_FEE * numberOfWords);
}

else if (numberOfWords <= 35)
{
textCost = TEXT_BASE_FEE + (TEXT_FLAT_FEE * 25) + (numberOfWords - 25) * LESS_OR_EQUAL_THAN_THIRTYFIVE;
}

else if (numberOfWords > 35)
{
textCost = numberOfWords * MORE_THAN_THIRTYFIVE;
}


String addLink, advancePay;
char link, advPay;

final float LINK_FLAT_FEE = 14.95F;
final float THREE_MONTH_ADV_DISCOUNT = 0.10F;

System.out.print("Would you like to add a link (y = yes or n = no)? ");
addLink = in.next();

link = addLink.charAt(0);
link = Character.toLowerCase(link);

if (link == 'y')
{
System.out.print("Would you like to pay 3 months in advance " + "(y = yes or n = no)? ");
advancePay = in.next();

advPay = advancePay.charAt(0);
advPay = Character.toLowerCase(advPay);

switch (advPay)
{
case 'y':

linkCost = (3 * LINK_FLAT_FEE) - (3 * LINK_FLAT_FEE) * THREE_MONTH_ADV_DISCOUNT;

break;

case 'n':

linkCost = LINK_FLAT_FEE;

break;
}
}

else
{
linkCost = 0;
}


String addGraphic;
char graphic;

System.out.print("Would you like to add graphics/pictures” + “(S = Small, M = Medium, L = Large or N = None)? ");
addGraphic = in.next();

graphic = addGraphic.charAt(0);
graphic = Character.toUpperCase(graphic);
graphic = Character.toLowerCase(graphic);
switch (graphic)
{
case 's':

graphicCost = 19.07F;

break;

case 'm':

graphicCost = 24.76F;

break;

case 'l':

graphicCost = 29.33F;

break;

default:
graphicCost = 0;
}


float gst, totalBeforeGst, totalAfterGst;

final float GST_RATE = 0.05F;

totalBeforeGst = textCost + linkCost + graphicCost; //textCost & linkCost would not initialize

gst = totalBeforeGst * GST_RATE;

totalAfterGst = totalBeforeGst + (totalBeforeGst * GST_RATE);


System.out.printf("\t\t%-16s %11s\n", "Category", "Cost");
System.out.printf("\t\t%-16s %11.2f\n", "Text", textCost); //linkCost would not initialize
System.out.printf("\t\t%-16s %11.2f\n", "Link", linkCost); //textCost would not initialize
System.out.printf("\t\t%-16s %11.2f\n", "Graphic", graphicCost);
System.out.printf("\t\t%-16s %11.2f\n", "Total", totalBeforeGst);
System.out.printf("\t\t%-16s %11.2f\n", "GST", gst);
System.out.printf("\t\t%-16s %11.2f\n", "Total with GST", totalAfterGst);
}
}

我几乎完成了这段代码,Eclipse 建议我将 0 值分配给 textCost 链接费用 .有没有其他方法可以解决这个问题。如果我不分配 0 值,它们会出错(局部变量 XXX 可能尚未初始化)。有人可以向我解释为什么即使我用方程分配了两个变量也会发生这种情况吗?

谢谢。

编辑:我按照建议做了,只有在需要时才声明变量。我还添加了一些评论。

最佳答案

在我深入研究代码之前,提出三个建议:

  • 尽可能晚地声明变量,以便更容易理解代码。
  • 重构这个巨大的方法 - 目前它是巨大的。
  • 制作常数 static final领域。它们与对方法的任何特定调用无关,因此它们不应该是局部变量。

  • 现在对于实际问题,最简单的方法是确保每个可能的流实际上都分配了一个值或抛出了异常。所以对于 textCost ,将您的代码更改为:
    if (numberOfWords <= 25)
    {
    textCost = TEXT_BASE_FEE + (TEXT_FLAT_FEE * numberOfWords);
    }
    else if (numberOfWords <= 35)
    {
    textCost = TEXT_BASE_FEE + (TEXT_FLAT_FEE * 25) + (numberOfWords - 25) *
    LESS_OR_EQUAL_THAN_THIRTYFIVE;
    }
    else // Note - no condition.
    {
    textCost = numberOfWords * MORE_THAN_THIRTYFIVE;
    }

    对于 linkCost , 将您的 switch 语句更改为:
    switch (advPay)
    {
    case 'y':
    linkCost = (3 * LINK_FLAT_FEE) -
    (3 * LINK_FLAT_FEE) * THREE_MONTH_ADV_DISCOUNT;
    break;
    case 'n':
    linkCost = LINK_FLAT_FEE;
    break;
    default:
    throw new Exception("Invalid value specified: " + advPay);
    }

    现在您可能不想在这里抛出异常。您可能想再次循环,或类似的东西。您可能不想只使用裸 Exception - 但你应该考虑你想要使用的确切异常类型。

    并非总是可以做到这一点。编译器确定明确赋值的规则相对简单。如果您真的无法更改代码以使编译器像这样满意,您可以只分配一个虚拟初始值。不过,我建议尽可能避免这种情况。在您的第一种情况下,确实总是会分配该值 - 但在第二种情况下,当 advPay 时您确实没有给出值既不是“y”也不是“n”,这可能会导致以后难以诊断的问题。编译器错误可帮助您发现此类问题。

    不过,我再次强烈建议您重构此方法。我怀疑您会发现当每个方法中只有大约 10 行代码需要推理时,以及当每个变量在其第一次使用之前或第一次使用时声明时,为什么没有明确分配的东西会更容易理解。

    编辑:

    好的,彻底重构的代码如下。我不会声称它是世界上最好的代码,但是:
  • 它更具可测试性。您可以轻松地为它的每个部分编写单元测试。 printAllCosts不是很容易测试,但你可能有一个过载 Writer打印到 - 这会有所帮助。
  • 计算的每一位都在一个逻辑位置。链接和图形具有一小组可能的值 - Java 枚举在这里很合适。 (我知道它们很可能超出您当前的技能水平,但很高兴看到可用的内容。)
  • 我不再使用二进制浮点数,因为它们不适用于数字。相反,我在任何地方都使用整数美分并转换为 BigDecimal用于显示目的。见我的文章 .NET floating point欲了解更多信息 - 这一切都与 Java 相关。
  • 广告本身现在封装在一个类中。您可以根据需要在此处添加更多信息。
  • 代码在一个包中。诚然,目前所有这些都在一个文件中(这就是为什么只有 EntryPoint 类是公开的)但这只是为了 Stack Overflow 和我不必打开 Eclipse。
  • 有 JavaDoc 解释了正在发生的事情 - 至少对于一些方法。 (我可能会在实际代码中添加更多内容。我在这里的时间不多了。)
  • 我们验证用户输入,除了字数——我们在单个例程中执行该验证,这应该是可合理测试的。然后我们可以假设,每当我们要求输入时,我们都会得到一些有效的东西。
  • EntryPoint中的静态方法数有点令人担忧。感觉不是很糟糕 - 但我发现这通常是程序入口点的方式。请注意,那里与费用无关 - 基本上只是用户界面。

  • 这里有比以前更多的代码 - 但它(IMO)更具可读性和可维护性的代码。
    package advertising;

    import java.util.Scanner;
    import java.math.BigDecimal;

    /** The graphic style of an advert. */
    enum Graphic
    {
    NONE(0),
    SMALL(1907),
    MEDIUM(2476),
    LARGE(2933);

    private final int cost;

    private Graphic(int cost)
    {
    this.cost = cost;
    }

    /** Returns the cost in cents. */
    public int getCost()
    {
    return cost;
    }
    }

    /** The link payment plan for an advert. */
    enum LinkPlan
    {
    NONE(0),
    PREPAID(1495), // 1 month
    POSTPAID(1495 * 3 - (1495 * 3) / 10); // 10% discount for 3 months up-front

    private final int cost;

    private LinkPlan(int cost)
    {
    this.cost = cost;
    }

    /** Returns the cost in cents. */
    public int getCost()
    {
    return cost;
    }
    }

    class Advertisement
    {
    private final int wordCount;
    private final LinkPlan linkPlan;
    private final Graphic graphic;

    public Advertisement(int wordCount, LinkPlan linkPlan, Graphic graphic)
    {
    this.wordCount = wordCount;
    this.linkPlan = linkPlan;
    this.graphic = graphic;
    }

    /**
    * Returns the fee for the words in the advert, in cents.
    *
    * For up to 25 words, there's a flat fee of 40c per word and a base fee
    * of $3.00.
    *
    * For 26-35 words inclusive, the fee for the first 25 words is as before,
    * but the per-word fee goes down to 35c for words 26-35.
    *
    * For more than 35 words, there's a flat fee of 32c per word, and no
    * base fee.
    */
    public int getWordCost()
    {
    if (wordCount > 35)
    {
    return 32 * wordCount;
    }
    // Apply flat fee always, then up to 25 words at 40 cents,
    // then the rest at 35 cents.
    return 300 + Math.min(wordCount, 25) * 40
    + Math.min(wordCount - 25, 0) * 35;
    }

    /**
    * Displays the costs associated with this advert.
    */
    public void printAllCosts()
    {
    System.out.printf("\t\t%-16s %11s\n", "Category", "Cost");
    printCost("Text", getWordCost());
    printCost("Link", linkPlan.getCost());
    printCost("Graphic", graphic.getCost());
    int total = getWordCost() + linkPlan.getCost() + graphic.getCost();
    printCost("Total", total);
    int gst = total / 20;
    printCost("GST", gst);
    printCost("Total with GST", total + gst);
    }

    private void printCost(String category, int cents)
    {
    BigDecimal dollars = new BigDecimal(cents).scaleByPowerOfTen(-2);
    System.out.printf("\t\t%-16s %11.2f\n", category, dollars);
    }
    }

    /**
    * The entry point for the program - takes user input, builds an
    * Advertisement, and displays its cost.
    */
    public class EntryPoint
    {
    public static void main(String[] args)
    {
    Scanner scanner = new Scanner(System.in);

    System.out.println("Welcome!");
    int wordCount = readWordCount(scanner);
    LinkPlan linkPlan = readLinkPlan(scanner);
    Graphic graphic = readGraphic(scanner);

    Advertisement advert = new Advertisement(wordCount, linkPlan, graphic);
    advert.printAllCosts();
    }

    private static int readWordCount(Scanner scanner)
    {
    System.out.print("Enter the number of words in your ad: ");
    // Could add validation code in here
    return scanner.nextInt();
    }

    private static LinkPlan readLinkPlan(Scanner scanner)
    {
    System.out.print("Would you like to add a link (y = yes or n = no)? ");
    char addLink = readSingleCharacter(scanner, "yn");
    LinkPlan linkPlan;
    if (addLink == 'n')
    {
    return LinkPlan.NONE;
    }
    System.out.print("Would you like to pay 3 months in advance " +
    "(y = yes or n = no)? ");
    char advancePay = readSingleCharacter(scanner, "yn");
    return advancePay == 'y' ? LinkPlan.PREPAID : LinkPlan.POSTPAID;
    }

    private static Graphic readGraphic(Scanner scanner)
    {
    System.out.print("Would you like to add graphics/pictures? " +
    "(s = small, m = medium, l = large or n = None)? ");
    char graphic = readSingleCharacter(scanner, "smln");
    switch (graphic)
    {
    case 's': return Graphic.SMALL;
    case 'm': return Graphic.MEDIUM;
    case 'l': return Graphic.LARGE;
    case 'n': return Graphic.NONE;
    default:
    throw new IllegalStateException("Unexpected state; graphic=" +
    graphic);
    }
    }

    private static char readSingleCharacter(Scanner scanner,
    String validOptions)
    {
    while(true)
    {
    String input = scanner.next();
    if (input.length() != 1 || !validOptions.contains(input))
    {
    System.out.print("Invalid value. Please try again: ");
    continue;
    }
    return input.charAt(0);
    }
    }
    }

    关于java - 如何避免 'the local variable may not have been initialized' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1585513/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com