java-anti-pattern for instance initialization of double curly braces

Source: Internet
Author: User

Today when watching Springboot batch, see such a piece of code, directly to me, so I looked for a moment, found that the two curly braces {{called strength initializer

flatfileitemreader<person> reader =NewFlatfileitemreader<>(); //set the path to the CSV fileReader.setresource (NewClasspathresource ("People.csv")); //mapping data and domain models of CVS filesReader.setlinemapper (NewDefaultlinemapper<person>() {{Setlinetokenizer (NewDelimitedlinetokenizer () {{Setnames (NewString[] {"name"," Age","Nation","Address"});            }}); Setfieldsetmapper (NewBeanwrapperfieldsetmapper<person>() {{Settargettype (person.class);        }}); }});
1, what is the instance initializer for Java

1, when you usually create a map and put values, this is the way to do

Set New Hashset<>(); set. Add (1); set. Add (2); set. Add (3);

Or, initialize in a static block of code

Private Static Set New Hashset<>(); Static {    set. Add (1);     set. Add (2);     set. Add (3);}

Or, Jane writes this form of

Set New Hashset<integer>() {{    add (1);    Add (2);    Add (3);}} ;

You can then pass in as a function parameter:

SomeFunction (new hashset<integer>() {{    add (1);    Add (2);    Add (3); }});

The curly braces here are, in fact, a section of {} Local code:

Set New Hashset<integer>() {    {        Add (1);        Add (2);        Add (3);}    };

This will execute our code regardless of which constructor is used.

2, Rice mode memory leak

Original Blog Address: http://deepinmind.iteye.com/blog/2165827

Say it is an anti-pattern mainly for three reasons:

1. Readability

Readability is one of the most minor reasons. Although it makes programming easier and looks like the initialization of data structures in JSON:

{    "FirstName":"John"  , "LastName":"Smith"  , "Organizations" :     {      "0": {"ID","1234" }    , "ABC": {"ID","5678" }    }  }  

2. One instance, one type

Through the initialization of a double parenthesis we've actually created a new type! Each new map generated in this way implicitly creates a new type that cannot be reused. If you use it only once, it's understandable. But if this code is everywhere in a large application, it will add a lot of burden to your classloader, and your heap will hold references to those classes. Do you believe me? Compile the above code and look at the output of the compiler below. This is probably the case:

test$1$1$1. class   test$1$1$2. class   test$1$1. class   test$1. class   Test. class  

Only the outermost test.class is meaningful here.

But that's not the most important question.

3. Memory leaks!

The most important problem is the anonymous class. They hold a reference to the perimeter instance, which is simply a timed zhadan. Imagine that you put this seemingly NB HashMap initialization into an EJB or a very heavy object that contains the life cycle:

 Public classReallyheavyobject {//Just to illustrate ...    Private int[] tonsofvalues; Privateresource[] tonsofresources; //This method almost does nothing     Public voidQuickharmlessmethod () {Map source=NewHashMap () {{put ("FirstName","John"); Put ("LastName","Smith"); Put ("Organizations",NewHashMap () {{put ("0",NewHashMap () {{put ("ID","1234");                  }}); Put ("ABC",NewHashMap () {{put ("ID","5678");              }});          }});                     }}; //Some more code here    }  }  

There are many resources in this reallyheavyobject class that need to be released as soon as the Reallyheavyobject objects are garbage collected. However, calling the Quickharmlessmethod () method does not have any effect, as the map will soon be recycled.

Good.

We assume that another developer, who reconstructs this method, returns the map, or some part of the map:

 PublicMap Quickharmlessmethod () {map source=NewHashMap () {{put ("FirstName","John"); Put ("LastName","Smith"); Put ("Organizations",NewHashMap () {{put ("0",NewHashMap () {{put ("ID","1234");              }}); Put ("ABC",NewHashMap () {{put ("ID","5678");          }});      }});             }}; returnsource; }  

This is a serious problem! Now you have exposed all the states in the reallyheavyobject to the outside, because each inner class holds a reference to a perimeter instance, that is, the Reallyheavyobject instance. Do you believe me? Run the next procedure to see:

 Public Static void Main (string[] args) throws Exception {      new  reallyheavyobject (). Quickharmlessmethod ();      = Map.getclass (). Getdeclaredfield ("this$0");      Field.setaccessible (true);      System. out. println (field.  Get(map). GetClass ());  }  

That's true!. If you still don't believe it, you can also use the debugger to see the internal state of the returned map.

You will find references to the perimeter instances lying quietly in this anonymous hashmap subclass. All of these anonymous subtypes will hold one such reference.

Therefore, do not use this anti-pattern

You might say that if Quickharmlessmethod () is declared as static, it's not going to be a leak in 3, you're right.

But the worst problem in the code above is that even if you know how to use the map in this static context, the next developer might not notice that he could refactor or delete the static. They may also store the map in a single case, so you can hardly see from the code where there is a useless reallyheavyobject reference.

The inner class is a beast. It has caused a lot of problems and cognitive imbalances. The anonymous inner class is even more serious, because the person who reads the code may not be aware that he has packaged a perimeter instance and has passed the instance elsewhere.

The conclusion is:

Don't be smart, don't use double brackets to initialize.

java-anti-pattern for instance initialization of double curly braces

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.