Why is it necessary to declare a final type to access local variables from an internal class?

Source: Internet
Author: User

Go to: http://hi.baidu.com/projoy/blog/item/02ab26acc154380f4a36d645.html/cmtid/7cd450114ef07ef6c2ce7929

During spring, many methods use callback functions, so more internal classes are involved. When using internal classes, I found that accessing local variables from internal classes needs to be declared as final. I am confused and found some analysis articles. As follows:

This is analyzed from the compiler perspective:

Class
{
Public void shout (final int iargs)
{
Class B
{
Public void shout1 ()
{
System. Out. println (iargs );
}

}
B = new B ();
B. shout1 ();
}
}
Class C
{
Public static void main (string [] ARGs)
{
A A = new ();
A. Shout (5 );
}
} This code... why should I add final? I think this external class method directly transmits the parameter... execution method... generate a B object and call shout1. why should I add final? I know that the local variables in a method are released after they are used. final defines the lifecycle of this external method... but I just don't understand it .. can you tell me?
------------------ The explanation is as follows ------------------

Local internal classes directly access objects defined externally (including common variables). The Compiler requires that the parameter reference must be final.

Where:
1. It must be a local internal class, apparently including an anonymous internal class;
2. Internal class access external class objects must be directly accessed.
Check the following code. Note that a does not need to be final:
Class A1:
Class A1 {
Public void shout (INT iargs ){
Class B {
Public void shout1 (int ){
System. Out. println ();
}

}
B = new B ();
B. shout1 (iargs );
}
}
Class:
Class {
Public static void main (string [] ARGs ){
A1 A = new A1 ();
A. Shout (5 );
}
}

Let's look at this code again:
Class A1 {
Public void shout1 (){
System. Out. println ("hi ");
}

Public A1 shout (final int iargs ){
Class B extends A1 {
Public void shout1 (){
System. Out. println (iargs );
}
}
Return new B ();
}
}
Class:
Class {
Public static void main (string [] ARGs ){
A1 A = new A1 ();
C = new C ();
C. shoutc (A. Shout (5 ));
}
}
Class C:
Class C {
Void shoutc (A1 B ){
B. shout1 ();
}
}

Statement C. shoutc (A. Shout (5); after a. Shout (5) returns the value, the shout () method stack of A is cleared!
That is, iargs does not exist, while C. shoutc () calls B. shout1 (); to execute the system. Out. println (iargs) statement. Aren't you surprised? Haha.

Let's take a look at how the Java Virtual Machine implements this weird access: Some people think that this access can be completed because the iargs is final. Is it because of the lifecycle of variables? The method stack does not exist. Even if a variable exists, how can it be accessed? Imagine: Can a method access the final local variable defined by another method (not through the return value )?

Study the principle of this weird access execution and use reflection to detect local internal classes.
The compiler detects whether external variables are directly used in local internal classes: if an access request exists, a field of the same type will be defined, and an external variable will be used in the constructor to assign a value to the field defined by myself. Then, all the variables used in the local internal class are their own defined fields! Of course you can access it! See:
Class A1 $1 $ B
{
A1 $1 $ B (A1, int );

Private final int var $ iargs;
Private final A1 this $0;
}
A1 $1 $ B type objects use the var $ iars variable instead of the final int iargs variable in the shout () method. Of course, you can access it!

OK. Now the question is, why is final? Even if the external variable is not final, the compiler can do this: Define a variable of the same type and assign a value in the constructor.

The reason is that we can use external variables logically directly, and it looks like we are always using iargs variables (instead of assigning values to our own fields )!

Consider this situation: the local internal class uses the external variable iargs and performs value change operations on the variable, such as iargs ++. According to the preceding analysis, if the compiler permits iargs to be not final, var $ iargs is changed, and iargs is not changed! It is still 5 (var $ iargs is 6 ). To avoid this logic: You have used an external variable and changed the value of the variable, but the variable remains unchanged! The natural iargs is forced to be modified by final (so that the two values are always the same, or the object to which they are directed is always the same, the latter may be more important )!

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.