4 ms·
> Java has the first part down, for the class of checked exceptions: a function that doesn't throw can't call functions that do (except in try/catch blocks, but
by cesarb 2y ago
> Java has the first part down, for the class of checked exceptions: a function that doesn't throw can't call functions that do (except in try/catch blocks, but that's largely irrelevant).
That's not actually true, it's possible to do "sneaky throws" (https://www.baeldung.com/java-sneaky-throws https://www.baeldung.com/java-sneaky-throws) of a checked exception from a method which isn't declared to throw that checked exception. The classic example is Class.newInstance(), which propagates any exception from the called constructor. Other ways are calling code from JVM languages other than Java, which do not have the same "checked exception" concept (like Kotlin: see https://kotlinlang.org/docs/exceptions.html https://kotlinlang.org/docs/exceptions.html and https://kotlinlang.org/docs/java-to-kotlin-interop.html#checked-exceptions https://kotlinlang.org/docs/java-to-kotlin-interop.html#chec...), generics trickery to confuse the compiler, and manually creating JVM bytecode.
- tsimionescu 2y agoSure, but that's essentially the same as using explicit jumps through raw assembly instructions to go around C++'s destructor guarantees. That is, when your Java process runs non-Java code, of course this can defeat certain Java guarantees. No programming language can make promises for semantics of external code like this.
- cesarb 2y agoThat's still the case in pure Java code. The "Class.newInstance()" method is a public method on the core Java API, calling "MyClass.class.newInstance()" is mostly equivalent to "new MyClass()". And the generics trick in the "sneaky throws" article I linked is also pure Java code, without any calls to "sun.misc.Unsafe".
- tsimionescu 2y agoClass.newInstance() is a known unsafe method and has been deprecated for quite some time now (since Java 9). It's similar to Haskell's unsafePerformIO from this point of view. The generics hole is indeed interesting, but it's ultimately a known limitation of how generics were implemented in Java, the presence of type inference, and the design of the exception hierarchy, than an intentional feature. When inferring the type of T to apply in that example, there is no good unique solution: inferring T = Throwable would have been safer, but it makes many simple cases behave unexpectedly, especially with lambdas. Inferring T = RuntimeException is unexpected and unsafe, but in practice it makes many common cases be way more usable, so a call was made to do it, despite the hole. C++'s templates wouldn't have a similar problem, as they actually instantiate the definition at compile time and can re-check it. Also, there is no equivalent issue to the ambiguous inference, because C++ doesn't do type inference of this kind at all, and anyway there is no problem of the exception hierarchy. Even if there were, C++ could also take the opposite choice than Java, and explicitly infer the safer option when both `noexcept` and `potentially-throws` were possible. And of course Lombok is a tool for modifying the compilation of Java, so writing Lombok code is not exactly writing pure Java.