Unintended consequences of an anonymous class created just to add a block initialization block

This is a question about Java code, for example:

List<String> list = new ArrayList<String>() {{add("hello"); add("goodbye");}} 

where the programmer anonymously extended ArrayList just for the sake of moving to the instance initialization block.

Question: if the only intention of the programmer is to achieve the same as:

 List<String> list = new ArrayList<String>(); list.add("hello"); list.add("goodbye"); 

then what are the unintended consequences of his first method?

+4
source share
4 answers

The danger of executing such code (in the general case) is that you may violate the equals() methods. This is because there are two common patterns for equals() :

 public boolean equals(Object ob) { if (!(ob instanceof MyClass)) return false; ... } 

and

 public boolean equals(Object ob) { if (ob.getClass() != getClass()) return false; ... } 

The first will still work with the anonymous subclasses you are talking about, and the second will not. The second thing is considered best practice because instanceof is not necessarily commutative (the value of a.equals(b) may not equal b.equals(a) ).

In particular, in this case, the ArrayList uses the AbstractList.equals() method, which simply checks that the other object is instanceof the List interface, so you're fine.

This is what you need to know.

What I would suggest is to do it a little differently:

 List<String> list = new ArrayList<String>( Arrays.asList("hello", "goodbye") ); 

I am sure this is more verbose, but you are unlikely to get into trouble this way, since the resulting class is a "pure" ArrayList .

+15
source

I think the big problem here is that you are creating an inner class of the surrounding class. The list you created will have an implicit reference to the outer class.

This is usually not a problem. However, if you serialize this object (I think, in particular, that XStream , since I came across this myself), then the serialized form will contain a serialized outer class. Which is not at all what you usually expect, and can lead to unusual behavior!

I am using the initialization pattern above. As long as you understand the internal mechanism of the class, this is not a problem. BTW. I do not think that the problem of equality is a problem that goes beyond the realization of equality in derivations in general.

+5
source

The impact on code and / or memory performance is negligible (if even measurable).

The real hit here is that you make people stop, even for a beat, to think "what is this guy doing?"

If I have to do this 1000 times while I am reading your code, this is a performance issue.

The code should be easy to read - provided all requirements for performance, completeness and standards are met.

Most likely, you will become the person supporting your code. Kindly be with your future self and make the code as EASY to read as possible. If you are going to do some fancy stuff like this, you have a good reason and document it in the code. If the only reason is to show your chops as a programmer, you have failed in the real work of the programmer: making it difficult is easy.

+2
source

The first approach is also poorly suited for performance. A mess of memory with lots of anonymous classes is not very good. In addition, it will be slower at startup.

0
source

All Articles