Skip to content

Instantly share code, notes, and snippets.

@gdoenlen
Last active July 21, 2024 21:37
Show Gist options
  • Save gdoenlen/18b7a1252efc8add0ad2874f026ac1fa to your computer and use it in GitHub Desktop.
Save gdoenlen/18b7a1252efc8add0ad2874f026ac1fa to your computer and use it in GitHub Desktop.
Language features

These are the language features I think Java needs to solve the most of its fluidity issues.

Try as an expression

Try should be an expression much like switch. It would enable clearer try catch code.

var a = try {
    yield someFn();
} catch (SomeException ex) {
    yield default;
}

Brian Goetz already started conversations around this topic but using switch.

var a = switch (someFn()) {
   case A a -> a;
   case throws SomeException ex -> default;
};

A way to escape checked exceptions

Knowing what errors can be thrown is a good thing. Checked Exceptions provides this in Java, but they are infrequently used because the language doesn't make them easy to use. When you know an exception can happen there are 3 things you can do:

  1. You know how to handle it and can return a value or pivot in some direction. Checked exceptions are great for this. You know what can happen and can respond appropriately.
Something s;
try {
    s = someThrowingFunc();
} catch (SomeCheckedException ex) {
    s = default;
}
// continue on your way
  1. You know how to handle it but its a few calls up, you just check the exception and then handle it where appropriate. Checked exceptions are working as designed.
public A someFunc(Arg arg) {
   // do stuff
   try {
       return someThrowingFunc();
   } catch (SomeCheckedException ex) {
       return null;
   }
}

private A someThrowingFunc(Arg arg) throws SomeCheckedException {
    // check some stuff
    // calculate some other stuff
    return deeper(calculate(arg));
}

private A deeper(Arg arg) throws SomeCheckedException {
    if (arg.bar())
        throw new SomeCheckedException(arg);

    return arg.foo();
}
  1. This error just isn't possible. You know it, and if it does happen the whole code path is hosed. This adds tons of boilerplate and causes no one to use checked exceptions. The biggest culprit of this in the Java standard library, in my opinion, is IOException:
private A someFunc() {
   List<String> content;
   try {
       content = Files.readLines(Paths.get("/some/critical/file/that/should/be/present.txt");
   } catch (IOException ex) {
       // Not possible, if this happens the app is dead
       throw new UncheckedIOexception(ex);
   }

   return A.of(content);
}

This last situation makes checked exceptions hard to work with. I think it would be better to have something like Kotlins !! which is used to escape null checks in the compiler. I'd like to the same for escaping checked exceptions and trusting the programmer:

private A someFunc() {
    var content = Files.read!!(Paths.get(...));
    return A.of(content);
}

An alternative would be a throws SomeException unchecked clause:

private A someFunc() throws IOException unchecked {
    var content = Files.read(Paths.get(...));
    return A.of(content);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment