Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unintended consequences of anonymous class created just for sake of adding instance initialization block

This is a question about Java code such as:

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

where the programmer has extended ArrayList anonymously just for the sake of shoving in an instance initialization block.

The question is: if the sole intention of the programmer is merely to achieve the same as:

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

then what are the unintended consequences of doing it the first way?

like image 750
jjujuma Avatar asked Nov 30 '22 07:11

jjujuma


1 Answers

The danger of doing that sort of code (in the general case) is that you might break equals() methods. That's because there are two general templates 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're talking about but the second won't. Thing is, the second is considered best practice because instanceof isn't necessarily commutative (meaning a.equals(b) might not equal b.equals(a)).

Specifically in this case however ArrayList uses the AbstractList.equals() method which merely checks that the other object is an instanceof the interface List, so you're fine.

It is something to be aware of however.

What I would suggest is to do it slightly differently:

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

Sure it's more wordy but you're less likely to get in trouble this way as the resultant class is a "pure" ArrayList.

like image 125
cletus Avatar answered Dec 05 '22 01:12

cletus