【问题标题】:Catch block variable warning in Java在 Java 中捕获块变量警告
【发布时间】:2023-03-26 09:56:01
【问题描述】:

我尝试让我的代码在没有错误和警告的情况下编译为标准做法。不过,有一个烦人的警告,我知道如何在 .NET 中处理,但在 Java 中却不知道。假设我有一个这样的代码块:

    try {
        FileInputStream in = new FileInputStream(filename);
        return new Scanner(in).useDelimiter("\\A").next();
    } catch (FileNotFoundException ex) {
        LOG.log(Level.SEVERE, "Unable to load file: {0}", filename);
        return null;
    }

我收到一条警告说变量ex 未被使用。现在,我对ex 真的没用,我不想要ex,但我不知道该怎么办。在 .NET 中我可以这样做:

catch (FileNotFoundException)

没有变量,它将编译和运行而没有错误。

在 Java 中如何处理这种情况?我知道我可以创建一个局部变量并将其设置为 ex,但这似乎是一个愚蠢且浪费的解决方法来修复一个实际上并不需要的警告。

【问题讨论】:

  • 很多语言都说的太简单了,我不懂这个异常所以就忽略了。 Java 采取保姆式的方式告诉你这是一个值得处理的异常。

标签: java


【解决方案1】:

该警告是 IDE 警告,您应该可以将其关闭。

但是,引发 FileNotFoundException 的原因有很多,在这种情况下您会想知道原因。

根据您的设置,IntelliJ 将 ignoreignored 识别为故意忽略的异常或非空 catch 块作为可接受的。

【讨论】:

    【解决方案2】:

    几乎每次我认为我没有用异常时,一段时间后我都会想到一个异常。通常。

    如果您真的想不出任何值得对异常实例做的事情,那么是时候考虑一​​下您在程序流中没有确定处理异常的正确位置的可能性了。

    另一种可能性,也许更可能是您自己编写的异常,是您的异常没有提供从异常情况中恢复所需的内容。

    希望最不可能的可能性是您正在滥用异常系统来执行应该使用另一个流控制结构完成的操作,例如 if 或 while 块。

    我在我的代数整数计算器项目中对此感到疑惑,在该项目中,您可以(或将能够)做一些事情,例如查询 8 和 3√2 的最大公约数 (GCD) 是多少。答案当然是 √2,但是计算机需要某种算法,比如欧几里得算法,才能解决这个问题。

    所以我的程序将 8 除以 3√2。这会导致NotDivisibleException 被抛出。该异常应提供至少一个舍入函数,通过该函数将 8/3√2 舍入为代数整数。

    不过,有时我只想知道一个代数整数是否可以被另一个整除。例如,

        public static boolean isDivisible(AlgebraicInteger a, AlgebraicInteger b) {
            try {
                a.divides(b);
                return true;
            } catch (NotDivisibleException nde) {
                return false;
            } catch (AlgebraicDegreeOverflowException adoe) {
                return false;
            }
        }
    

    您可以想象,这给了我一个未使用的异常警告。这就是为什么我想知道NotDivisibleException是否是对异常系统的滥用的主要原因。

    这里有什么替代方案?我可以重写isDivisible 中的除法函数,这样它就可以在不触发任何异常的情况下为我提供真假。

    因此,这个未使用的异常警告比几乎逐字复制除法函数更可取。

    至于AlgebraicDegreeOverflowException,我认为这是一个运行时异常,应该由调用者而不是isDivisible 捕获。 adoe 子句因此受到打击。

    所以这给我留下了一个未使用的异常警告。我想也许我能做的最好的事情就是将它限制在一次出现,将它封装在一个函数中,而不是每次我需要做一个简单的可分性测试时都重复它。

    在这个程序的 Scala 版本中,我可以使用“_”来表示我实际上不需要异常对象。或者我什至可以重载模运算符,以便它可以处理 AlgebraicInteger 操作数,或定义隐式转换等。

    但那是 Scala。在 Java 中,只有三个选项:

    • 以某种方式使用异常
    • 禁止警告
    • 忽略警告

    不过,最后两个是一样的。

    我知道这是八年前的问题。我很想知道你决定在FileNotFoundException 的情况下做什么。

    在您的情况下,我想我会决定至少在使用getMessage() 函数检索异常消息后记录它。您可能无法在此处添加一些额外的上下文,这可能会提出不同的解决方案。

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 在这种情况下,他最好使用ex,而不是取消警告。
      【解决方案4】:

      记录异常。无论如何,在追踪错误时它总是有用的。

      【讨论】:

      • 我同意:知道为什么找不到文件总是有用的。您可以使用精细或最佳级别记录异常。
      • 强烈同意,帮自己一个忙,LOG.log(Level.SEVERE, "Unable to load file: " + filename, ex);
      • 他确实记录了异常。他的问题是来自编译器的虚假警告信息。
      • 将异常添加到日志条目将为您提供有关问题的更多信息(例如,文件不存在 VS 文件不可访问)。
      【解决方案5】:

      您应该记录异常。根据FileInputStream API,可以抛出FileNotFoundException“如果文件不存在,是目录而不是常规文件,或者由于某些其他原因无法打开读取。”如果您遇到该问题,在日志文件中包含更多详细信息(例如堆栈跟踪)将更容易修复。

      【讨论】:

        【解决方案6】:

        基本上,您是 SOL(您必须声明变量并接受警告),因为 JAVA 在其对开发人员的处理方式中有点躁郁症,或者至少是保姆式的;这又是一个例子。 JAVA 让您声明 catch 变量,即使您从不打算使用它。这意味着您有一个未使用的变量,只是等待引起问题。虽然有很多关于“你需要使用这个异常变量”的 cmets,但这些 cmets 没有抓住问题的重点。问题是“我如何不得到这个未使用的变量警告”,该示例使用 FileNotFound 异常,但它可能是任何异常。问题不是关于 FileNotFound 异常,而是关于未使用的变量警告。

        异常类型对于这个问题无关紧要。例如,我有一个管理数据缓冲区的类。它可能会由于几个原因引发异常,其中之一是数据缓冲区已满。因此,如果我尝试将数据放入完整缓冲区,我的函数可以接收到该异常。这是在这种情况下它可以收到的唯一例外。我有一个使用此类的函数检测异常并扩展缓冲区。它不关心异常变量,它不记录异常,它处理异常并继续前进。除了异常,我可以返回一个指示缓冲区已满的标志,但是会破坏异常处理系统(系统中有其他例程,此异常是一个错误,我通过日志记录和向用户发送消息来处理它们等)

        所以,我可以将 IDE 设置为忽略未使用的变量警告。但这不是一个好主意,因为有时不使用变量表示真正的问题(我错过了一段代码,或者我可能忘记结束块注释或其他东西)。或者,至少,我有一段未使用的代码,将来可能会增加混乱。我可以压制警告,但这只是一个杂碎。底线是我必须放入一个未使用的变量,记录它为什么未使用,并设法解决这个警告(所以 QA 不会抱怨),所有这些都是因为 JAVA 想要保护我免受自己的伤害。

        <rant>
        

        这是我在使用 JAVA 时遇到的主要问题。 JAVA 声称它们是一种严肃的编程语言,供严肃的专业人士在严肃的项目中使用。然而,他们随后假设这些同样严肃的专业人士总是犯愚蠢的错误,他们需要受到保护,以免犯下这些错误。这几乎就像告诉外科医生他们不能使用手术刀,因为他们可能会割伤自己。如果您正在为业余爱好者制作玩具编程语言,那么请提供您想要的所有保护。但是,如果您声称要为专业人士制作一种语言,那么请为专业人士提供完成工作所需的工具。他们是专业人士,给他们专业的工具。诸如强制定义未使用的变量、不允许运算符重载、没有无符号原语以及基本上将用户类视为二等公民等限制了工具集,并表明专业工程师并不那么专业。我不介意这些警告——它们有助于加快开发过程。我不喜欢缺少完整的工具集。这会导致变通、混乱和全新的错误来源。

        不管怎样,对你的咆哮感到抱歉

        </rant>
        

        【讨论】:

          【解决方案7】:

          在 Java 中没有“将ex 标记为已使用”的干净方法,除非使用它。

          注意,但是根据its documentation FileNotFoundException 也可以在“[...] 文件确实存在但由于某种原因无法访问时抛出,例如当尝试用于打开一个只读文件进行写入。”

          因此,我建议您使用异常,同时打印异常中的消息。

          我知道这并不能回答一般问题,但我几乎想不出一个例外,当它发生时我至少不会记录一些信息。

          【讨论】:

          • 我将此标记为最佳答案,因为它在第一句话中最直接地回答了我的问题。
          • “通过打印异常消息”这是使用异常文本 (toString()) 作为用户界面项。我会说这是一个坏主意:文本没有国际化,并且通常是针对程序员而不是用户的形式。
          • 更多关于是否应该使用异常消息的想法:stackoverflow.com/questions/7320080/…
          • @Raedwald 异常中的 message 肯定可以本地化,如您链接到的问题中所述。 Throwable.toString() 不是您通常会发送给用户的东西。
          【解决方案8】:

          如果我使用 javac 编译该代码,我不会收到警告,因此您使用的是不同的编译器或不同的设置 - 我假设 IDE 用于未使用变量的特殊设置。

          在 Eclipse 中,我使用注释逐行关闭此类警告,在这种情况下:@SuppressWarnings ("unused") 在前面的行中。

          【讨论】:

          • 你是对的,我更正了它,因为在命令行上,我没有收到警告。我被他In .NET I could just do: ... catch (FileNotFoundException) ... without the variable and it will compile and run with no error.这句话弄糊涂了,但在其他地方,他清楚地谈到了警告。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-02
          • 2011-01-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多