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

微笑、不失礼 提交于 2020-01-02 06:13:27

问题


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?


回答1:


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.




回答2:


I think the big issue here is that you're creating an inner class of the surrounding class. The list you create will have an implicit this reference to the outer class.

This isn't normally a problem. However, if you serialise this object (I'm thinking particularly of using XStream since I've run into this myself) then the serialised form will contain the serialised outer class. Which isn't at all what you'd normally expect and can result in peculiar behaviour!

I use the above initialisation pattern a lot. So long as you're aware of the inner class mechanism then it's not a problem. bTW. I don't think the equality issue is an issue beyond that of equality implementations on derivations in general.




回答3:


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

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

If I have to do that 1,000 times while I read your code, THERE is the performance problem.

Code should be easy to read - so long as all performance, completeness, and standards requirements are met.

Most likely you are going to be the person maintaining your code. Be nice to your future self, and make the code as EASY TO READ as possible. If you're going to do some fancy schmancy stuff like that, have a good reason and document it in code. If the only reason is to show off your chops as a programmer, you have failed in the real job of a programmer: to make the difficult easy.




回答4:


The first approach is also bad for performance. Cluttering memory with lots of anonymous classes isn't good. Also it will be slower at startup.



来源:https://stackoverflow.com/questions/671644/unintended-consequences-of-anonymous-class-created-just-for-sake-of-adding-insta

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!