Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> Java has an obviously better type system

How does Java have a better type system? Java's generics are unsound, while Go's generics are sound. Java's generics do type erasure, while Go does not. Java's type system is not unified, it does not have a top type (an int is not an Object, int vs. Integer etc.).



Java methods support type arguments. Go methods do not leading to convoluted gymnastics for straightforward behaviour.

> Java's type system is not unified, it does not have a top type

Neither does Go for that matter.

Go's lack of visibility modifiers and package scope namespace cause very common gotchas mentioned in https://itnext.io/we-need-to-talk-about-the-bad-sides-of-go-....

There is a Manning book about Go: https://www.manning.com/books/100-go-mistakes-and-how-to-avo... . And these are not rare mistakes. Everyone makes them and some of those mistakes are repeated again and again in every Go project. (Esp the for-loop ones). I have found programming in Go needing the kind of alert, defensive mindset I adopt for C++ which is quite exhausting. Not so much for Java.

However, to be honest, Rust is probably the only the language where you can relax your "defect-analysis" mind thread while coding - with the exception of async Rust.


Anecdotally, but I feel like Java's type system allows me to write code that gives me more guarantees about the soundness and correctness of my codebase.

One example I can think of is Java's annotations vs Go's closest alternative, struct tags [0], which are just strings added to struct fields that specific libraries can act on; at best these are only checked at runtime, the compiler or type system will not help you with those.

[0] https://go.dev/ref/spec#:~:text=A%20field%20declaration%20ma...


Haskell’s type system does type erasure, is it “worse” for that?


No. Both type erasure and monomorphization have always been legitimate ways to compile generic code. IIRC, the issue with Java is that type erasure is sometimes a leaky abstraction.


What exactly do you mean by "leaky" here? Can you give an example?

My main issue with non-erased generics is that they actually break reasoning wrt. parametric polymorphism as soon as you allow for pattern matching or even just .isInstanceOf on type parameters. Suddenly a function which takes a List<A> can do entirely different things depending on what A is... and that takes away a powerful reasoning tool.


It’s leaky due to reflection, but type erasure is not a problem in itself. .NET did away with type erasure, but it had a cost in terms of language ecosystem of the platform - not erasing List<A> into List will bake the variance of List into the runtime, and thus other languages have to use the same model.


Erasure's not the end of the world, but it'd be nice to have access to the generic class without having to pass it in.

    Collection<Foo> values = ...
    Foo[] array = values.toArray(Foo[]::new);
Not the worst, but not the best either.

There are many situations where the code I implemented could have been far cleaner with reified generics.


Java has records, pattern matching, and proper enums.

As of writing this comment, golang does not allow you to have generics on methods as far as I'm aware.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: