Skip to content

Instantly share code, notes, and snippets.

@milleniumbug
Last active May 7, 2023 21:49
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milleniumbug/3bd74fcdce6355d1355f05cec1a909b2 to your computer and use it in GitHub Desktop.
Save milleniumbug/3bd74fcdce6355d1355f05cec1a909b2 to your computer and use it in GitHub Desktop.
why Java sucks
Let's start with: Java is a language that one would create when looking at the state of C++ in early 90's and thinking how can I make it "better" in terms of being error prone.
But this was only an evolution instead of a revolution STL introduced as a way of programming
(sure, they weren't first, but I'd say they were the first to introduce it to masses)
The rest is a consequence of being backward
Problem with null pointers? Still there
Speaking of pointers in Java, I like how Java fans continuously say "they're not pointers, they're references"
But guess what happens when you access a null reference? A NullPointerException is thrown
So what I don't like?
Collections API. Just terrible.
The "unmodifiable" lists are your regular lists that throw exceptions on modifications
DON'T PROVIDE THESE OPERATIONS IN THE FIRST PLACE FFS
but that would mean actually designing your class hierarchy instead of doing something similar to "Animal - Mammal - Dog" examples
Also there's List.get(int index) method
and both ArrayList and LinkedList implement List
for the latter it actually means traversing the list until the element of this index is found
Sure you can check whether the List is an instance of a tag interface RandomAccess
BUT WHY DO YOU PROVIDE IT IN THE FIRST PLACE
let it be a method in RandomAccess
oh wait you can't actually say "this variable is both a List and RandomAccess" so you have to make all these auxiliary classes
...actually, no, you actually can do this for function parameters, thanks to generics
so this can't be the reason.
this is when you notice you're in a deep hole of helplessness
There's no type deduction of variables (like C++ auto or C# var). Fixed in Java 10, they introduced var.
so you have to write MyLongClassNameClass x = new MyLongClassNameClass(arguments); // FML
There's "diamond operator" in Java 7 which helps a bit for generics
so you can write Map<String, Integer> m = new HashMap<>();
instead of Map<String, Integer> m = new HashMap<String, Integer>();
Oh, regarding generics
Only reference types can be passed as a generic
So in Java 8 you have Stream<T>, IntStream, DoubleStream, LongStream, Optional<T>, OptionalInt, OptionalDouble, OptionalLong
there's only three of the "special" classes, so I guess they thought writing these for all 8 of primitive types was too annoying
Arrays are covariant, which is terrible
(this means Dog[] is convertible to Animal[])
but this introduces type safety violations because you can assign a Cat to what should be Animal[] and what would be a compiler error is now a runtime error
(there's code which is ran on assignment that checks whether the dynamic type is correct)
...the same problem exists in C#, but there you can get away with not using arrays quite far (see above remark about generics and notice it doesn't apply to C#)
I've already mentioned null pointers? Yeah, they're a problem
The current stance on null pointers among Java programmers is: don't
Another problem is lack of operator overloading
Have fun writing BigInteger a = new BigInteger("2364564564564645645"); BigInteger b = BigInteger.valueOf(2); BigInteger c = BigInteger.valueOf(3); BigInteger d = b.multiply(a.add(c));
Also, checked exceptions
They're a total pain in Java
Both the fact they're completely abused in standard library
and the fact you can't handle them in generic scenarios
You have some kind of visitor that visits some kind of a data structure? Have fun writing it without kludges or declaring the function as throws Exception, which means now more code has to catch exceptions which will never happen
(also you can't generically declare that a function throws an exception when some another function does)
this sums it up
https://twitter.com/mariofusco/status/739698058582196224
There are issues in bad class design all over the place
Because of curiosity I looked up how Java does random numbers
https://docs.oracle.com/javase/8/docs/api/java/util/Random.html
Just look at the setSeed method
for now, let's put aside the fact that Random is not an interface
...oh, look SecureRandom is a subclass of Random
IOW the non-deterministic random generator is a subclass of the deterministic random generator
https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html#setSeed-long-
clearly says it violates the contract of setSeed
...well of course
there's no other option than to violate the contract with such class design
Liskov Substitution Principle is violated all over the place
and Cloneable is a tag interface
fucking retarded
(by "tag interface" I refer to interfaces which have no methods, so the only operation you can do is x instanceof TheInterface)
so if you have a list of Cloneables, you can't clone them because the .clone method isn't a method of Cloneable
Another problem is auto-unboxing of the "reference types wrapping primitive types"
like: byte -> Byte, char -> Character, int -> Integer and so on
conditional operator ?: normally does conversion to a "common type" in all languages where it exists
but in Java true ? 5 : (Integer)null throws a NullPointerException (!)
because instead of converting the 5 from int to Integer, it converts (Integer)null to int
which, as expected, is a lossy conversion
because we're mapping {null} ∪ [Integer.MIN_VALUE, Integer.MAX_VALUE] to [Integer.MIN_VALUE, Integer.MAX_VALUE] instead of doing the reverse
I can't explain this in another way than "someone was drunk that day"
You know what is fun? URL class doing DNS lookup in an equals method
this means the answer is different whether you're connected to the internet or not (!)
god forbid if you're using them in a hash table
@jcoppola
Copy link

yo... I love this rant! Java is f*cking retarded and soo verbose. The new streams API is an abomination; shoving something in because its fashionable but does not have the syntax that makes using the programming technique efficient or clear. A small amount of clever coding you can do groupbys with comparators and for loops treemap. Anyway... I enjoyed this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment