JDK8 's essay (_LAMBDA) discussion on variable use scope of expression

Source: Internet
Author: User

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

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.