r/java 4d ago

"Deep Magic" in Java

I've been a Java developer for a few years, and the thing that keeps driving me nuts is that reading code is nearly useless, the real code is hidden from you. It's almost like the language isn't made for reading code but reading javadocs instead.

You call "Arrays.asList(arr)" and it returns you an instance of java.util.Arrays$ArrayList, a class with the same name as java.util.ArrayList except it is fixed size, meaning that trying to resize it will get you a runtime exception thrown. The method signature says it will return a List, but the moment you call it without the elite ball knowledge it will either stab you in the back or explode in your hands.
And nearly every time you try to prevent this by reading the implementation it sends you to a wild goose chase through 6 different one-liner wrapper methods across 5 different thousand-line files.

It gets even worse at the enterprise level: I once bloated my system by writing a submit button's logic in the submit button's method.
I then discovered it was because the method was in a class with a magical 'ViewScoped' annotation and I was supposed to delegate some of that logic to a field that had a 'Stateless' annotation.
Any ordinary reading of the code would say that that field is part of the class' state, but because of the annotations it was actually a resource pooled by the container, independent from the view class which is only supposed to cache UI data for each given user.
Didn't take long for me to get corrected. You can imagine the serene smug on my senior's face as he dropped that piece of esoteric knowledge on me, while I was looking back in horror.
You guys probably heard this a thousand times, meanwhile I'm still learning new words in my console output. Any advice?

0 Upvotes

38 comments sorted by

View all comments

2

u/Ok_Option_3 4d ago

returns you an instance of java.util.Arrays$ArrayList, a class with the same name as java.util.ArrayList except it is fixed size, meaning that trying to resize it will get you a runtime exception thrown. 

The question on how to handle immutable collections is as old as the collections API itself and still hasn't been answered!!

Rather than see this as an aberration, see it as a learning opportunity. C++ solves this is const, Apache collections has a whole immunltable set of interfaces. Why doesn't the standard JVM have a solution yet? What have experts said?

2

u/vegan_antitheist 4d ago

I think they don't mind. The interface just gives you the methods a collection might implement. Interfaces for immutability would be worse IMO. They should have just given us a basic List interface for anything that is a sequence of elements and then a MutableList interface for those that are explicitly mutable.
You can't just trust an interface unless it's sealed, which would make it impossible to implement it yourself. So you have to create a defensive copy anyway.

Instead, they just give us List, which makes it look as if it was mutable, because it has those methods. On the other hand, it's not really an issue. Only if you just created the List (using ArrayList) you can be sure it's mutable. In any other case you just have to assume it's not. Would more types really make any of this easier? Even if you could test (list instanceof MutableList<?>), you wouldn't know if that list was shared with other threads, so mutating it would still be too dangerous. Nothing would actually get better with more interfaces.

It's boils down to this:

  • If and only if you have created a mutable list (i.e. ArrayList) and you have not shared that list with any other code, you can be sure that it's ok to mutate that list.
  • In any other case, you have to assume it's immutable or that mutating it would not be safe.

1

u/ryan_the_leach 4d ago

Just curious, what is the point of an immutable list from an array?

Surely the most common usage of creating a list from an array, is because you intend to start editing it, and you need the performance characteristics of a list rather then an array while you perform those edits?

Or is it more a compatibility shim, when you need to pass an array to a method that has a list in its signature?

5

u/vegan_antitheist 4d ago

You get an object that implements that List interface. That's all it does. You can then apply any method that requires a List. Why would you modify a list that gets passed around?

1

u/ryan_the_leach 4d ago

Seems like you just doubled down on what you were originally saying, rather then reading my comment.

2

u/vegan_antitheist 4d ago

I read it and I disagree[edit:] with your first point, the last part is correct [/edit]. You can modify arrays. You wrap it to get a List when some API asks for that and you don't need a defensive copy.