lambda variable usage and scope of use
concept Universal capturing variable capture variables
What is capture variables
Let's take a look at some code examples:
Public class localclassexample { StaticString regularexpression ="[^0-9]"; Public Static void Validatephonenumber(String phoneNumber1, String phoneNumber2) {Final intNumberlength =Ten;//Valid in JDK 8 and later: //int numberlength = ten;Class PhoneNumber {String Formattedphonenumber =NULL; PhoneNumber (String phonenumber) {//numberlength = 7;String Currentnumber = Phonenumber.replaceall (RegularExpression,"");if(currentnumber.length () = = numberlength) Formattedphonenumber = Currentnumber;ElseFormattedphonenumber =NULL; } PublicStringGetNumber() {returnFormattedphonenumber; }//Valid in JDK 8 and later://public void Printoriginalnumbers () {//System.out.println ("Original numbers is" + PhoneNumber1 +//"and" + phoneNumber2);// }} PhoneNumber MyNumber1 =NewPhoneNumber (PhoneNumber1); PhoneNumber MyNumber2 =NewPhoneNumber (PHONENUMBER2);//Valid in JDK 8 and later://Mynumber1.printoriginalnumbers (); if(Mynumber1.getnumber () = =NULL) System.out.println ("First number is invalid");ElseSystem.out.println (" first number is"+ Mynumber1.getnumber ());if(Mynumber2.getnumber () = =NULL) System.out.println ("Second number is invalid");ElseSystem.out.println ("Second number is"+ Mynumber2.getnumber ()); } Public Static void Main(String ... args) {Validatephonenumber ("123-456-7890","456-7890"); }}
The code for the example is a format handler for the regular expression of the phone number, using an inner class for processing.
OK, the above statement is wrong. is not an inner class , it is a local class .
An inner class is a class that is directly defined inside a class, whereas a class that is defined in the inner {} of a local class is a block that can be a method or an if statement, and so on.
finalint10;
The above is a local variable in the Validatephonenumber method of the class Localclassexample.
According to the criteria before JDK8, a local class can access a local variable if the local variable should be declared final.
So in the example above, Numberlength is declared final and can be accessed directly from the PhoneNumber class.
This access is called captured variable, which captures variables .
the utilization of capture variables after JDK8
Effective Final
To say a digression, after JDK8, a local variable even if it is not final, but if it is effective final, it can be capture variable. What do you mean? See below:
Before Jdk8, if we did not use final to define this numberlenth, then there would be error, information.
And if it's jdk8, it's not going to go wrong, entries.
The so-called "effective final" refers to a variable that has never been changed after the declaration, then the variable is "effective final".
If you change it halfway, you can't. Such as:
Method Parameters Access
Off-topic.
publicvoidprintOriginalNumbers() { System.out.println("Original numbers are " + phoneNumber1 + " and " + phoneNumber2); } }
The above code fragment accesses PhoneNumber1 and PhoneNumber2, both of which are derived from the parameters in the Validatephonenumber method below.
publicstaticvoidvalidatePhoneNumber( String phoneNumber1, String phoneNumber2) {
Concept popularization shadowing
What is shadowing ?
Shadowing is shielded.
Public classshadowtest { Public intx =0;//row 1Class Firstlevel { Public intx =1;//Row 2 voidMethodinfirstlevel (intx) {//Row 3System. out. println ("x ="+ x); System. out. println ("this.x ="+ This. x); System. out. println ("shadowtest.this.x ="+ Shadowtest. This. x); } } Public Static void Main(String ... args) {Shadowtest St =NewShadowtest (); Shadowtest.firstlevel fl = St.NewFirstlevel (); Fl.methodinfirstlevel ( at); }}
Guess the running result first.
Answer:
23this1ShadowTest.this0
Line 1 line 2 Line 3 in the code is the variable of x.
Global variables for row 1:class
Line 2: Global variables for inner classes
Line 3: Parameters of the method
Java is characterized by the same name, but the scope is different, so you need to add a modifier where each variable is used to tell the JVM exactly which variable you are taking.
As can be seen from the example, these three x are shielded from each other.
By using X Direct value, it is definitely the value that is passed directly from the method variable.
By this.x, this refers to the inner class of this small scope implementation, so is the inner class of the x=1.
The shadowtest.this.x that rises to the top is the global variable of the whole class X, and the result is naturally 0.
Shielding mainly depends on the scope of the function and the prefix of the call time to determine which variable is obtained.
The performance of capture variable and shadowing in lambda expressions
lambda expression supports capture variable
Public class lambdascopetest { Public intx =0; Class Firstlevel { Public intx =1;voidMethodinfirstlevel (intx) {//The following statement causes the compiler to generate //The error "Local variables referenced from a lambda expression //must be final or effectively final ' in statement A: // //x =;Consumer<integer> Myconsumer = (y), {System.out.println ("x ="+ x);//Statement ASystem.out.println ("y ="+ y); System.out.println ("this.x ="+ This. x); System.out.println ("lambdascopetest.this.x ="+ Lambdascopetest. This. x); }; Myconsumer.accept (x); } } Public Static void Main(String ... args) {Lambdascopetest St =NewLambdascopetest (); Lambdascopetest.firstlevel fl = St.NewFirstlevel (); Fl.methodinfirstlevel ( at); }}
Look at the picture better:
The original source of the variable x is the Firstlevel method of the inner class methodinfirstlevel the parameter.
In the invocation of the lambda expression on line 23rd, the read was successful, so this is the behavior of a capture variable, so the lambda expression supports capture variable.
The output is:
x23y23this.x1LambdaScopeTest.this.x0
There's a little bit of burning here.
First, this.x=1 and lambdascopetest.this.x = 0 have been explained in the previous, OK no problem.
X=23 y=23 needs to be highlighted.
First, the result of the x=23 is derived from the following parameter in the main method.
fl.methodInFirstLevel(23);
The parameter passed in is the value of x 23,system.out.println ("x =" + x); The value of x is directly derived from the method parameter 23 and is a direct use of the capture variable.
And how did y=23 come to it?
Consumer<integer> Myconsumer = (y), {System. out. println("x ="+x);//Statement ASystem. out. println("y ="+y);System. out. println("this.x ="+ This. x);System. out. println("lambdascopetest.this.x ="+ lambdascopetest. this. x);};Myconsumer. Accept(x);
In the code above, let's simplify:
Consumer<Integer> myConsumer = (y) -> { System.out.println("y = "y); }; myConsumer.accept(x);
If you can't see clearly, then continue simplifying:
Consumer<Integer> myConsumer = (y) -> { System.out.println("y = "y); }; myConsumer.accept(23);
As you can see, the lambda expression implements the Consumer<integer> function interface Accept method, then the generic is already qualified to be an Integer, then the input (y) is the parameter T of the Accept (T T), t also becomes the integer type accordingly. The external parameter is the value of the x,x itself is 23, then the value of Y is naturally 23, from the external transmission, and capture variable no relationship.
lambda expression does not support shadowing
The above gives me shadowing example, actually changes our own example to change is shadowing.
The shadowing is implemented with the same variable name masking.
We changed the y in the lambda expression to x so that the x is the same as the int x defined by the method.
In the previous example, this should be done with a mask that does not interfere with each other, but the error message comes along.
From the error message, we can see that the lambda expression does not really implement a scope, the scope of the implementation of which in the Javadoc language is only a semantic scope, so the duplicate definition will make the compiler think you are repeating the definition.
As for why, that is the problem with the JVM layer design, the future of how changes are unclear, the current standard is the case.
つづく???
JDK8 's essay (_LAMBDA) discussion on variable use scope of expression