How can I handle an IOException which I know can never be thrown, in a safe and readable manner?

后端 未结 8 1812
生来不讨喜
生来不讨喜 2021-02-02 12:07

\"The major difference between a thing that might go wrong and a thing that cannot possibly go wrong is that when a thing that cannot possibly go wrong go

相关标签:
8条回答
  • 2021-02-02 12:50

    Consider using the form

    throw new RuntimeException("This should never happen", e);
    

    instead. This allows you to convey meaning to the maintainer to follow you, both when reading the code but also SHOULD the exception happen to be thrown in some strange scenario.

    EDIT: This is also a good way to pass exceptions through a mechanism not expecting those exceptions. E.g. if you have a "get more rows from the database" iterator the Iterator interface does not allow to throw e.g. an FileNotFoundException so you can wrap it like this. In the code USING the iterator, you can then catch the runtimeexception and inspect the original excpetion with getCause(). VERY useful when going through legacy code paths.

    0 讨论(0)
  • 2021-02-02 12:57

    If your position is that this is so unlikely and should just end the program, use an existing runtime exception, even RuntimeException itself (if not IllegalStateException).

    try {
      ....
    
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    }
    
    0 讨论(0)
  • 2021-02-02 13:01

    Don't just tank your entire application with a RuntimeException when you encounter an unlikely error condition. RuntimeException should be reserved for programmer errors, and IOException is most likely not caused by programmer error.

    Instead, encapsulate the lower level exception in a higher level exception and rethrow. Then handle the higher level exception up the call chain.

    For example:

    class SomeClass {
    
      public void doActions() {
        try {
          someAction();
        } catch (HigherLevelException e) {
          notifyUser();
        }
    
        someOtherUnrelatedAction();
      }
    
      public void someAction() throws HigherLevelException {  
        try {
          // user lower-level abstraction to do our bidding
        } catch(LowerLevelException e) {
          throw new HigherLevelException(e);
        }
      }
    
      public void someOtherUnrelatedAction() {
        // does stuff
      }
    }
    

    Most likely the call stack that threw the exception was performing some task in your application. Instead of force crashing your entire application with a RuntimeException figure out what to do when the problem occurs during that task. For example, were you trying to save a file? Don't crash, instead notify the user there was an issue.

    0 讨论(0)
  • 2021-02-02 13:02

    You are probably better off throwing the superclass and more generic exception IOException at any point in your code which involves reading or writing from the file.

    The file may exist when your class's constructor runs, but that doesn't guarantee that:

    1. It exists when methods are called
    2. It's writable/readable
    3. Another thread doesn't access it and somehow screw up your streams
    4. The resource doesn't go away in the middle of processing

    etc.

    Instead of reinventing the wheel, I would say just re-throw IOException wherever the JDK/java.io classes you are using force you to do so.

    Also I for one hate classes that throw Exceptions from their constructor - I'd get rid of these if I were you.

    0 讨论(0)
  • 2021-02-02 13:06

    The usual pattern to deal with this is exception chaining. You just wrap the FileNotFoundException in a RuntimeException:

    catch(FileNotFoundException e) {
        throw new RuntimeException(e);
    }
    

    This pattern is not only applicable when an Exception cannot occur in the specific situation (such as yours), but also when you have no means or intention to really handle the exception (such as a database link failure).

    Edit: Beware of this similar-looking anti-pattern, which I have seen in the wild far too often:

    catch(FileNotFoundException e) {
        throw new RuntimeException(e.getMessage());
    }
    

    By doing this, you throw away all the important information in the original stacktrace, which will often make problems difficult to track down.

    Another edit: As Thorbjørn Ravn Andersen correctly points out in his response, it doesn't hurt to state why you're chaining the exception, either in a comment or, even better, as the exception message:

    catch(FileNotFoundException e) {
        throw new RuntimeException(
            "This should never happen, I know this file exists", e);
    }
    
    0 讨论(0)
  • 2021-02-02 13:07

    I did a little googling and found this glob of code. It's a bit more flexible of an approach me thinks

    Compliments of this article

    class SomeOtherException extends Exception {}
    
    public class TurnOffChecking {
      private static Test monitor = new Test();
      public static void main(String[] args) {
        WrapCheckedException wce = new WrapCheckedException();
        // You can call f() without a try block, and let
        // RuntimeExceptions go out of the method:
        wce.throwRuntimeException(3);
        // Or you can choose to catch exceptions:
        for(int i = 0; i < 4; i++)
          try {
            if(i < 3)
              wce.throwRuntimeException(i);
            else
              throw new SomeOtherException();
          } catch(SomeOtherException e) {
              System.out.println("SomeOtherException: " + e);
          } catch(RuntimeException re) {
            try {
              throw re.getCause();
            } catch(FileNotFoundException e) {
              System.out.println(
                "FileNotFoundException: " + e);
            } catch(IOException e) {
              System.out.println("IOException: " + e);
            } catch(Throwable e) {
              System.out.println("Throwable: " + e);
            }
          }
        monitor.expect(new String[] {
          "FileNotFoundException: " +
          "java.io.FileNotFoundException",
          "IOException: java.io.IOException",
          "Throwable: java.lang.RuntimeException: Where am I?",
          "SomeOtherException: SomeOtherException"
        });
      }
    } ///:~
    
    0 讨论(0)
提交回复
热议问题