错误 "The local variable age may not have been initialized" 是由于尝试捕获多个异常而发生的

The error "The local variable age may not have been initialized" occurs as a result of attempting to catch more than one exceptions

尝试捕获多个异常时出现错误“局部变量 age 可能尚未初始化”。

你好。解决了上一个问题后,我决定对程序做一个小改动,使用JOptionPane 将控制台中的打印转换为简单的GUI,并且出现了新的错误。我试图捕获两个名为 NumberFormatException 和 NullPointerException 的特定异常。 NumberFormatException 是由于在 JOptionPane.showMessageDialog 的空白 space 中输入数字以外的字符而发生的,因为该变量已声明为双精度。单击 X 符号或取消按钮会导致 NullPointerException。 为了捕获 NullPointerException,我在 NumberFormatException 之后添加了一些额外的代码。 但是,在测试运行程序时,结果控制台出现如下错误:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized
The local variable age may not have been initialized

at Welcome.main(Welcome.java:10)

其实在class的开头我已经声明了变量age为double,尽管如此,'may not have been initialized'的错误依然存在。你能提供这个错误的解决方案吗?如果代码 catch(NullPointerException e){JOptionPane.showMessageDialog(null,"Program canceled.") 不存在,则不会发生该错误。

顺便问一下,除了正题,请您也解释一下JOptionPane.showMessageDialog括号内的'null'的含义和用法。非常感谢。 我的代码如下:

import javax.swing.*;

public class Welcome {
    public static void main(String[] args) {
        double age;
        while (true) {
            try {
                age = Double.parseDouble(JOptionPane.showInputDialog(null, "please enter your age and we will define your age group"));
            } catch (NumberFormatException e) {
                JOptionPane.showMessageDialog(null, "Input Error. "
                        + "Please enter a number corresponding to your age only.", "error", JOptionPane.ERROR_MESSAGE);
            } catch (NullPointerException e) {
                JOptionPane.showMessageDialog(null, "Program canceled.");
                continue;
            }
            if (age < 0) JOptionPane.showMessageDialog(null, "Warning!Negative values cannot hold true.",
                    "warning", JOptionPane.WARNING_MESSAGE);
            else if (age <= 0.1) JOptionPane.showMessageDialog(null, "You are a newborn.");
            else if (age <= 1) JOptionPane.showMessageDialog(null, "You are an infant.");
            else if (age <= 3) JOptionPane.showMessageDialog(null, "You are a toddler.");
            else if (age <= 5) JOptionPane.showMessageDialog(null, "You are a preschooler.");
            else if (age <= 13) JOptionPane.showMessageDialog(null, "You are a school-aged child.");
            else if (age <= 19) JOptionPane.showMessageDialog(null, "You are an adolescent and a denarian.");
            else if (age <= 29) JOptionPane.showMessageDialog(null, "You are a vicenarian.");
            else if (age <= 39) JOptionPane.showMessageDialog(null, "You are a tricenarian.");
            else if (age <= 49) JOptionPane.showMessageDialog(null, "You are a quadragenarian.");
            else if (age <= 59) JOptionPane.showMessageDialog(null, "You are a quinquagenarian.");
            else if (age <= 69) JOptionPane.showMessageDialog(null, "You are a sexagenarian.");
            else if (age <= 79) JOptionPane.showMessageDialog(null, "You are a septuagenarian.");
            else if (age <= 89) JOptionPane.showMessageDialog(null, "You are a octogenarian.");
            else if (age <= 99) JOptionPane.showMessageDialog(null, "You are a nonagenarian.");
            else if (age <= 109) JOptionPane.showMessageDialog(null, "You are a centenarian.");
            else if (age <= 150) JOptionPane.showMessageDialog(null, "You are a supercentenarian.");
            else if (age > 150)
                JOptionPane.showMessageDialog(null, "Warning!The value entered is too large to be processed.", "warning", JOptionPane.WARNING_MESSAGE);
        }
    }
}

问题是,如果你的代码输入了下面几行代码,变量age实际上不会被赋值:

     catch (NumberFormatException e) {
        JOptionPane.showMessageDialog(null, "Input Error. "+ "Please enter a number corresponding to your age only.", "error", JOptionPane.ERROR_MESSAGE);
    }

Java 在编译时检查是否所有变量都已正确初始化。如果编译器认为一个变量可能在下一条指令之前还没有初始化,就会得到这个错误。

你可以通过简单地初始化变量来解决这个问题:

     catch (NumberFormatException e) {
        age = 0D;
        JOptionPane.showMessageDialog(null, "Input Error. "+ "Please enter a number corresponding to your age only.", "error", JOptionPane.ERROR_MESSAGE);
    }

但我认为正确的做法是:

     catch (NumberFormatException e) {
        JOptionPane.showMessageDialog(null, "Input Error. "+ "Please enter a number corresponding to your age only.", "error", JOptionPane.ERROR_MESSAGE);
        continue;
    }

关于你的第二个问题,关于 showMessageDialog,您可以在 documentation 中读到:

public static void showMessageDialog(Component parentComponent, Object message) throws HeadlessException
    Brings up an information-message dialog titled "Message".
    Parameters:
        * parentComponent - determines the Frame in which the dialog is displayed; if null, or if the parentComponent has no Frame, a default Frame is used
        * message - the Object to display

假设有人在弹出窗口中输入“你好”。 JOptionPane.showInputDialog方法returns就好了,"Hello"交给了Double.parseDouble。这导致 NumberFormatException 被抛出,因此代码切换到 catch 块。

此 catch 块将打印一条关于需要输入数字的消息,然后.. 代码将继续。毕竟,捕捉意味着你处理它(如果你想做某事然后继续异常过程,那么 re-throw 它,或者做其他事情来影响控制流,比如 continue; 你做在 NullPointer catch 块中执行!)

代码继续进入 if (age < 0) 并且此代码无法执行,因为在这种情况下未设置 age。编译器知道这一点并会拒绝编译它。

这里的主要解决方案似乎是编写控制流,如果用户一开始没有输入数字,if (age < 0) 块永远不会 'hit'。你知道怎么做 - 你正在用一个 while 循环和另一个 catch 块中的 continue; 语句来做到这一点。

或者,选择一个年龄作为默认值或占位符,以指示用户尚未输入任何内容。但这听起来不像是这种情况的最佳解决方案 - 在用户实际输入年龄之前,您不想处理年龄。

尝试将所有年龄验证登录移动到 try 块内,其中 age 变量已 100% 定义。像那样:

try {
    // here you initialise the "age" variable
    final double age = Double.parseDouble(JOptionPane.showInputDialog(null, "please enter your age and we will define your age group"));
    
    // here you work with the "age" variable
    if (age < 0) JOptionPane.showMessageDialog(null, "Warning!Negative values cannot hold true.",
                    "warning", JOptionPane.WARNING_MESSAGE);
    else if (age <= 0.1) JOptionPane.showMessageDialog(null, "You are a newborn.");
    else if (age <= 1) JOptionPane.showMessageDialog(null, "You are an infant.");
    else if (age <= 3) JOptionPane.showMessageDialog(null, "You are a toddler.");
    else if (age <= 5) JOptionPane.showMessageDialog(null, "You are a preschooler.");
    else if (age <= 13) JOptionPane.showMessageDialog(null, "You are a school-aged child.");
    else if (age <= 19) JOptionPane.showMessageDialog(null, "You are an adolescent and a denarian.");
    else if (age <= 29) JOptionPane.showMessageDialog(null, "You are a vicenarian.");
    else if (age <= 39) JOptionPane.showMessageDialog(null, "You are a tricenarian.");
    else if (age <= 49) JOptionPane.showMessageDialog(null, "You are a quadragenarian.");
    else if (age <= 59) JOptionPane.showMessageDialog(null, "You are a quinquagenarian.");
    else if (age <= 69) JOptionPane.showMessageDialog(null, "You are a sexagenarian.");
    else if (age <= 79) JOptionPane.showMessageDialog(null, "You are a septuagenarian.");
    else if (age <= 89) JOptionPane.showMessageDialog(null, "You are a octogenarian.");
    else if (age <= 99) JOptionPane.showMessageDialog(null, "You are a nonagenarian.");
    else if (age <= 109) JOptionPane.showMessageDialog(null, "You are a centenarian.");
    else if (age <= 150) JOptionPane.showMessageDialog(null, "You are a supercentenarian.");
    else if (age > 150)
                JOptionPane.showMessageDialog(null, "Warning!The value entered is too large to be processed.", "warning", JOptionPane.WARNING_MESSAGE);
} catch (NumberFormatException e) {
     JOptionPane.showMessageDialog(null, "Input Error. "
                        + "Please enter a number corresponding to your age only.", "error", JOptionPane.ERROR_MESSAGE);
} catch (NullPointerException e) {
    JOptionPane.showMessageDialog(null, "Program canceled.");
                continue;
}