【问题标题】:Java: Is it possible to throws IOException once and for all?Java:是否可以一劳永逸地抛出 IOException?
【发布时间】:2014-12-02 21:42:28
【问题描述】:

我是 Java 新手。而且我发现在“main”和所有打开文件的方法中继续写throws IOException 真的很烦人。例如:

class something{    
    public static void main(String[] args) throws IOException{
            myobj abc = new myobj();
            abc.read_file("this_file.txt");
            abc.insert("text");
    }
}

class myobj{
            ....

           public void read_file(String file_loc) throws IOException{
                blablabla
            }
    }

在这种情况下,我已经写了两次“抛出 IOException”。有没有办法一劳永逸地处理这个问题?

编辑: 感谢所有好的答案。很多人建议使用 try-catch 语句。 我读到了 try and catch 语句,我真的很困惑。我的问题是我应该在哪里继续编写我的代码,即 abc.insert("text")abc.read_file("this_file.txt") 之后的 try catch 语句中?我应该在 catch 块内还是在它外面继续?这才是真正让我困惑的地方。

【问题讨论】:

  • 捕捉main中的异常并适当处理。
  • 这是一个语言特性,不是你应该反对的。
  • 是的,我知道这看起来很无聊……但这非常非常重要。经过一段时间的 Java 更复杂的工作...你会喜欢 Java 异常管理... ;)
  • 是的,没有 NullPointerException 就没有 java。你会看到很多这个学习这种语言的人。 :)

标签: java


【解决方案1】:

没有包罗万象的“这个类中的所有方法都抛出这个异常”,你必须在每个方法上声明异常(例如,read_file 等)或在方法中处理它。这就是检查异常的意义所在:为了确保在每个阶段都清楚它们可能来自何处以及处理它们的位置。


注意:main 不应该抛出,你应该捕获异常并处理它。

【讨论】:

    【解决方案2】:

    主要投给谁?没有人。

    Java 有已检查和未检查的异常。已检查的异常让您别无选择:您要么必须捕获它们,要么将它们添加到 throws 子句中的方法签名中。

    未经检查的异常不需要处理。

    您始终可以选择捕获已检查异常并将其作为自定义未检查异常重新抛出。

    我会这样写:

    class something{    
        public static void main(String[] args) 
            try {
                myobj abc = new myobj();
                abc.read_file("this_file.txt");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    class myobj{
                ....
    
               public void read_file(String file_loc) throws IOException{
                    blablabla
                }
        }
    

    【讨论】:

    • 但这正是默认异常处理程序无论如何都会做的事情,那么这样做有什么好处呢?就个人而言,如果我看到catch-printStackTrace 构造,我会非常怀疑,因为它们是“摆脱”异常的常见症状,而不是正确处理它们。不幸的是,流行的 IDE 通过其默认代码生成来鼓励这种习惯用法。
    • 我通常会采用不同的方法,并让 main 声明它是已检查的异常。然后,我在 try/finally 中进行任何必要的清理,让异常冒泡。这样做的原因是,有时(无论是用于测试还是集成)其他代码可能会调用另一个类的 main,其中伪 CLI 参数以编程方式或声明方式或其他方式计算得出。除非我有充分的理由,否则我绝不会期望我的主要函数会专门从命令行调用。
    • “正确处理它们”是什么样的,尤其是在这个人为的、简单化的例子中?无论如何都知道处理应该不仅仅是打印堆栈跟踪,但在这种情况下,它是一个主要方法。这是行的结尾。
    【解决方案3】:

    我是 Java 新手。

    嗨,我希望你喜欢你的学习。有效地学习一门新的编程语言意味着学习用该语言编写代码的惯用方式(即使是我们主观上觉得很烦人的方式。)

    这不是 Java 独有的。无论你使用 C#、Python、C++ 还是 Haskell,你都会发现一些令人讨厌的东西。那么问题是,在避免这种烦恼的过程中,你有什么价值。

    如果您通过避免烦恼而变得更有效率,那么您将获得更多权力。否则,我会听从 Maya Angelou 的建议:"If you don't like something, change it. If you can't change it, change your attitude."

    而且我发现继续写作真的很烦人 在“main”和所有打开文件的方法中抛出 IOException。

    在现实生活中的开发中,您将处理比主要异常更多的非主要异常(可能只有一个主要异常。)

    那么,什么是阈值,主要/(所有其他功能)的比例,使烦恼是合理的和建设性的?一主一功能?一主一打?一主一百?

    在需要使用 Java 完成的所有管道和麻烦事中,在 main 函数上声明异常是一种很少用的情感练习。

    因此,对它持保留态度,但在我的专业意见(18 年,Java、C++、Python 和许多其他废话)中是这样的:声明你的异常,即使在 main 上。

    为什么?因为其他程序可能会调用您的主程序。也就是说,您的 Java 程序可能是从控制台调用的,也可能是从另一个程序嵌入(可调用?)。

    我已经为测试或开发可嵌入的系统做了很多工作。所以,在这种情况下, 你想声明这些异常。然而,由于这样的程序是为独立和嵌入式使用而设计的,这是我遵循的一般模式(类似 java 的伪代码,比实际代码要简化得多):

    class UtilityDelegate {
        UtilitytDelegate(){ .... }
    
        void performWork(File f) throws IOException {
            // do something with file
        }
    }
    
    public class SomeUtility {
        public static void main(final String[] args) throws IOException {
            File f = null;
            try{
                // do something that could throw an exception
                f = new File(args[0]);
                performWork(f);
            } finally {
                // do necessary clean-up, if any, such as closing file handles,
                // sockets, flushing database changes, pray to Lord Xenu, whatever
    
                if( f != null ){
                    try{
                        f.close();
                    }catch (IOException e){
                        e.printStackTrace(); // or use a logging mechanism or whatever
                    }
                }
            }
        }
    }
    

    现在,您的程序可以从命令行调用:

    java SomeUtility myfile
    

    或者来自另一个java类:

    public class SomeUtilityClient{
        public static void main(final String[] args){
            // for brevity, I'm omitting the case when the utility might
            // call System.exit() itself.
            try{
                SomeUtility.main("a-pre-defined-filename");
            } catch(IOException e){
                someLog("call to utility failed, see exception", e);
                System.exit(-1);
            }
            System.exit(0);
        }
    }
    

    可以提出一个论点,即这样的 java 客户端应该通过另一个方法名调用嵌入式程序,而不是 main。这是公平的,在许多情况下,这是更好的方法。

    但只要考虑一下为什么要在任何地方声明异常的原因或方法,即使是在你的 main 上。

    【讨论】:

      【解决方案4】:

      main 方法不需要抛出任何东西。

      class something{    
          public static void main(String[] args) 
              try {
                  myobj abc = new myobj();
                  abc.read_file("this_file.txt");
                  System.exit(0);
              } catch (IOException e) {
                  e.printStackTrace();
                  System.exit(1);
              }
          }
      }
      

      我知道你可能会觉得这个语言特性很烦人,但相信我,它远没有管理不传播异常的代码那么令人沮丧。你花了好几个小时想知道为什么你的代码没有做某事,然后你偶然发现了这个:

      try {
          doSomethingImportant();
      }
      catch(Exception e) {
         // Nah can't be bothered
      }
      

      【讨论】:

        【解决方案5】:

        简单地说,没有。

        有两种处理异常的方法:

        1. 您可以在当前方法(在您的情况下为 main)中处理该异常,方法是使用 try-catch 包围引发异常的 API,并在 catch 块中编写代码来处理它,或者
        2. 在方法签名上添加“抛出 IOException”,在这种情况下,您会强制方法的调用者处理它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-11
          • 1970-01-01
          • 2015-09-25
          • 2016-07-20
          • 2017-06-16
          • 2016-09-13
          相关资源
          最近更新 更多