Autoboxing's evil twin, auto-unboxing should knock the score down a few points. Integer a = null; int b = 42; if (a == b) {} // throws NullPointerException
Or my favourite... Short w = 42; Short x = 42; out.println(w == x); // true Short y = 1042; Short z = 1042; out.println(y == z); // false
Rating 26 years of Java changes
221–230 of 327 posts
Re: Rating 26 years of Java changes
#222Earlier quoted context omitted.
Yeah, it works until it isn't. And they good luck debugging it. I'd prefer simple obvious linear code calling some functions over this declarative magic any day. cronService.schedule("xxx", this::refresh); This isn't any harder than annotation. But you can ctrl+click on schedule implementation and below easily. You can put breakpoint and whatnot.
never had any issues debugging as I am never debugging the scheduler (that works :) ) but my own code. and what exactly is “cronService”? you write in each service or copy/paste each time you need it?
Re: Rating 26 years of Java changes
#223Earlier quoted context omitted.
They are absolutely failed concept in Java. Every first popular library uses unchecked exceptions, including famous Spring. Java streams API does not support checked exceptions. Even Java standard library nowadays includes "UncheckedIOException". Kotlin, Scala: both languages grown from JVM and do not support checked exceptions.
Spring has a special error handling strategy where the whole request is allowed to fail, punting error handling off to the caller. A lot of code that throws checked exceptions is simply dangerous to use with Java streams because the execution order of stream operation is not obvious and possibly non-deterministic. For this reason, streams were never intended to also handle errors. Reactive frameworks are much better…
From the type system PoV, they could have just written something like `interface Runnable { void run() throws X; }` and now `forEach` would have been written like ` void forEach(Runnable r) throws X`. And repeat that for all stream operations, promoting `X` everywhere, so if your mapper function throws SQLException, the whole pipeline will throw it.
It even works today with some limitation (there's no way for `X` to get value of `SQLException|IOException` union type), but with some generic improvements it could work.
But they decided to not touch this issue at all. So now people will fool compiler with their tricks to throw checked exceptions like unchecked (or just wrap them with UncheckedXxxException everywhere, I prefer that approach).
Re: Rating 26 years of Java changes
#224Earlier quoted context omitted.
I don't really feel that Java uses proven features. For example they used checked exceptions. Those definitely do not seem like proven feature. C++ has unchecked exceptions. Almost every other popular language has unchecked exceptions. Java went with checked exceptions and nowadays they are almost universally ignored by developers. I'd say that's a total failure. Streams another good example. Making functional API fo…
Checked exceptions are for errors that are not possible to prevent. How else should the caller know which exceptions are really likely to happen? Modules absolutely achieved their primary goal: stopping libraries from accessing JDK internals without the application's knowledge. The ecosystem is slow on the uptake since split packages and access to internal APIs is endemic, but it is happening ever so slowly. I wish l…
The same way, caller can know which exceptions are really likely to happen in TypeScript, C++, Python. Or in modern Java which avoids checked exceptions anyway. By reading documentation or source code. That's perfectly fine and works for everyone.
And you highlighted one big issue with checked exceptions. You've claimed that those exceptions are "really likely to happen".
When I'm writing reading data from resource stream, the data that's located next to my class files, IO Exceptions are really unlikely to happen.
Another ridiculous example of this checked exception madness:
var inputStream = new ByteArrayInputStream(bytes);
var outputStream = new ByteArrayOutputStream();
inputStream.transferTo(outputStream); // throws IOException? wtf???
This code can throw OutOfMemoryError, StackoverflowError, but never IOException. Yet you're forced to handle IOException which doesn't happen. And that's the issue with checked exceptions.There's no correspondence between checked exceptions and likelihood of their occurence. NullPointerException probably happens more than any checked exception. The division between checked exceptions and unchecked exceptions is absolutely arbitrary and makes sense only at caller place, never in called function signature.
> Modules absolutely achieved their primary goal: stopping libraries from accessing JDK internals without the application's knowledge. The ecosystem is slow on the uptake since split packages and access to internal APIs is endemic, but it is happening ever so slowly. I wish libraries could opt into not being part of the unnamed module.
"Slow" is an understatement. I don't see this happening at all. Last time I tried to write very simple application with modules, I spent so many hours banging my head over various walls, that I probably will not do another attempt in a foreseeable future.
Re: Rating 26 years of Java changes
#225Earlier quoted context omitted.
Your IDE can do that?
What if I'm just looking at a pull request on GitHub? Sure I can check out the branch etc but that's just adding more friction.
Sometimes I doubt most hacker news commentors have ever worked in big corpo environments where you have to regularly review large PR in some broken webapp like GitHub.
Re: Rating 26 years of Java changes
#226Earlier quoted context omitted.
Or my favourite... Short w = 42; Short x = 42; out.println(w == x); // true Short y = 1042; Short z = 1042; out.println(y == z); // false
I’ll bite. Why does this not work as you’d expect?
For performance reasons boxed Short objects are interned when they represent values in the range -127 to +128 so for 42 the pointers will point to the same interned object after 42 is autoboxed to a Short. Whereas 1042 is outside this interning range and the autoboxing creates two distinct objects with different pointers.
It's very simple but (a) non-obvious if you don't know about it and (b) rather wordy when I spell it out like this :)
In general in Java you want obj.equals(other) when dealing with objects and == only with primitives, but autoboxing/unboxing can cause confusion about which one is dealing with.
In other other words, the surprise ought to be that w == x is true, not that y == z is false!
Re: Rating 26 years of Java changes
#227Earlier quoted context omitted.
You can get pretty good performance out of Java these days, so long as you know to avoid stuff like boxed primitives and the streams api, as they generally have god-awful memory locality, and generally don't vectorize well.
Yeah, I know there are even oddballs using it for HFT and the like - I like Java a lot, but even I find that a bit peculiar. Edit: actually, if someone here is using it for something like that I'd love to hear the rationale...?
It's mostly a trade-off. Java's tooling, reliability and ecosystem is some of the best around. Even though building high performance software in Java is a bit of a pain, looking at the bigger picture, it's often still worth it.
Re: Rating 26 years of Java changes
#228Earlier quoted context omitted.
What other language made them think checked exceptions were a good idea?
They are a good idea. Checked errors are so important for correctness. HN’s darling Rust exclusively uses checked errors.
Re: Rating 26 years of Java changes
#229Earlier quoted context omitted.
It's another thing they adopted from Kotlin, since Kotlin is supposed to be a "better java". Now Java is retroactively adopting Kotlin freatures.
Kotlin didn't invent type inference, it's a feature from ML.
Re: Rating 26 years of Java changes
#230Earlier quoted context omitted.
Or my favourite... Short w = 42; Short x = 42; out.println(w == x); // true Short y = 1042; Short z = 1042; out.println(y == z); // false
If JEP 401 is ever delivered (Value Classes and Objects), then this sort of problem should go away.