Hacker News new | ask | show | jobs
by nathanwh 1017 days ago
> Name a language and I'll tell you a much worse issue.

Not sure if the offer was only open to OP but I'll bite. How about Java?

3 comments

1. Java does not allow to implement new interfaces for classes without modifying their signature - much more limiting than Rusts foreign trait rule. You cannot make a foreign class implement your new interface.

2. Java does not allow to create wrappers without incurring a significant memory overhead. A wrapper will consume at least 32 bytes of memory on 64-bit systems just for itself, when in Rust this can be 0.

3. Even if you define a wrapper, it would be way less ergonomic than in Rust - there is nothing like AsRef / Deref / From / Into etc machinery in Java.

I haven't used Java for some time, but when I did it didn't have non-nullable types. I think collections were also type erased which is pretty bad.

JNI is a nightmare.

Strings are UTF-16.

Dealing with installing the JVM, whatever the hell "classpath" is, tweaking GC parameters etc. is a big downside.

Despite that it's definitely one of the saner languages out there.

Boxed Integers will compare with == for values -128 to 127 but not other valid ints.

    Integer.valueOf(5) == Integer.valueOf(5)
    true

    Integer.valueOf(200) == Integer.valueOf(200)
    false
That's a quirk of the language, sure, but it's barely an issue, and definitely not a worse issue. Don't get many wrong, Java has many issues, but this barely qualifies.

You don't compare non-primitives (which boxed integers are) with == in Java, you use the equals method.

You definitely shouldn't compare them that way. But it still allows you to. That becomes a fairly big issue where you have the behavior working when you test it out and suddenly it doesn't work when the values become larger. Sure, an experienced Java developer will know this. How about a developer that is new to the language? Not as likely. I've personally lost over 6 hours to that one years and years ago.
CPython has the same thing, although with reverse syntax: you can use is to compare -5 to 256 rather than ==. I assume Java is also doing some caching of that int range for speed reasons.
What I really like in the space is what OCaml and Smalltalk do, where ints are full objects unto themselves with essentially a bit in the object header that says "interpret the rest of this object header as an int and if you need to do object style ops, you don't need a pointer to the class as the class is int", so there's no boxed versus unboxed int distinction in the first place. So primitive types versus class types exists at the VM level, but not the language level.

Obviously Java doesn't have the luxury of that decision at this point. But a lot of goofy parts of languages are string of fairly rational choices with unintended consequences.

You're not supposed to, but I've certainly found code out there that does use == to compare boxed integers because the test cases they used happen to work.

And in fact when I googled to find the exact range where it switches from cached integers to truly creating new objects, the top link was at best highly misleading. https://www.tutorialspoint.com/check-two-numbers-for-equalit...

.valueOf() will sometimes give different instance, sometimes not.

If you want a instance, I recommend new :)

Well, unfortunately autoboxong will silently call valueOf(). So

    Integer val1 = 5;
    Integer val2 = 5;
    Integer val3 = 200;
    Integer val4 = 200;
will have you ending up with val1 and val2 being equal with ==, but val3 and val4 won't be.

The general reply is 'you're holding it wrong', but that doesn't make it any less absurd. That's what the PHPers say about "123" < "456A" < "78" < "123".

IDK it makes sense to me.

Unless you call `new` there's no guarantee that you have a different object.