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