Why anonymous intrinsic class parameters must be final type (reprinted)

Source: Internet
Author: User

Why the anonymous intrinsic class parameter must be final type
Transferred from: http://feiyeguohai.iteye.com/blog/1500108

1) from the theory of programming language: The local inner class (i.e., the inner class defined in the method), because it is inside the method itself (can appear at the formal parameter definition or method body), thus accessing the method of local variables (formal parameters or local variables) is justified. It's natural.


2) Why add a restriction to Java: Only the final type local variables can be accessed?


3) The designer of the Java language compiler is of course fully implemented: The local inner class can access all local variables in the method (because: Theoretically this is a natural requirement), but: the compiler technology is not achievable or expensive.


4) Where is the difficulty?
The life cycle of the local variable is inconsistent with the life cycle of the local inner class object!


5) The method F is called to generate a variable i in its call stack, at which time a local inner class object Inner_object is generated, which accesses the local variable I. When the method F () runs, the local variable i is dead and does not exist. However: Local Inner class object Inner_ An object may also persist (it will only die if no one references the object again), and it will not end up dead with Method F (). At this point: there is a "ridiculous" result: the local inner class object Inner_object to access a nonexistent local variable i!


6) How can it be achieved? When the variable is final, the copy is directly used as a data member in the local interior by "copying" the final local variable. This way: when the internal class accesses local variables, it actually accesses the "replica" of the local variable (i.e.: This copy represents the local variable). Therefore: When the true local variable in the run stack dies, the local inner class object can still access the local variable (actually accessing the "replica"), giving the impression that the "lifetime" of the local variable is prolonged.


So: The core question is: How can we make: access to "replicas" and access to real original local variables, the semantic effect is the same?
When the variable is final, if the base data type, because its value is unchanged, thus: its copy is the same as the original amount. The semantic effect is the same. (if: Not final, there is no guarantee that the copy is consistent with the original variable because: the original variable is changed in the method, and the local inner class is replaced by a copy)

When a variable is final, a reference type, because its reference value is constant (that is, always pointing to the same object), and thus: its copy, like the original reference variable, always points to the same object (because it is final, thus guaranteeing: only point to this object, and then not to other objects), to achieve: Replicas accessed in the local inner class are always the same as the original objects accessed in the method code: The semantic effect is the same. Otherwise: When the original variable is changed in the method, and the local inner class is changed, there is no guarantee that the copy is consistent with the original variable (so: they should have been the same variable.)

Bottom line: The rule is a helpless one. It also shows that the design of programming language is limited by the implementation technology. This is one example. Because: I see a lot of people hold this view: design and ideas are the most important, the implementation of the technology is irrelevant, as long as you make the design and rules, can be achieved.



Now let's see if I want to implement an example that calls Absclass anonymously in a method:
public static void Test (final String s) {
or final String s = "Axman";
Absclass C = new Absclass () {
public void M () {
int x = S.hashcode ();

SYSTEM.OUT.PRINTLN (x);

}
};
Other code.
}

From the code point of view, the method of inner class defined inside a method to access local variables or method parameters inside an external method is very natural, but how to get this variable when the inner class compiles, because the inner class is a normal class in addition to its life cycle within the method. So how does the local variable or method parameter outside of it be accessed by the internal class? The compiler actually did this when it was implemented:


public static void Test (final String s) {
or final String s = "Axman";


Class Outerclass$1 extends absclass{

Private final String S;
Public outerclass$1 (String s) {
THIS.S = s;
}
public void M () {
int x = S.hashcode ();

SYSTEM.OUT.PRINTLN (x);

}
};

Absclass C = new outerclass$1 (s);
Other code.
}


That is, the variables of the outer class are passed to the private members of the inner class as arguments to the constructor method.
If there is no final, then:
public static void Test (String s) {
    //or string s = "Axman";
  absclass c = new absclass () {
   public void M () {
     s = "other";
  }
 };
  System.out.println (s);
 
  compiles:
  public static void Test (String s) {
     //or string s = "Axman";

Class Outerclass$1 extends absclass{

Private String S;
Public outerclass$1 (String s) {
THIS.S = s;
}
public void M () {
s = "other";

}
};

Absclass C = new outerclass$1 (s);

}

  and you see
  public static void test (String  s) {
    //or string s = "Axman";
  absclass C = new Absclass () {
   public void M () {
     s  = "Other";
  }
 };
  System.out.println (s);
 

The syntax is a s, in the inner class has been changed, but the results printed out you think is the same s but still the original "Axman",
Can you accept such a result?
So final is syntactically constrained by the fact that two different variables are actually consistent (represented by the same variable).

Ext.: http://blog.csdn.net/onisland/article/details/5807637

why anonymous inner classes and local inner classes can only access final variables

Is the problem of the scope of the variable, because the anonymous inner class appears inside a method, and if it wants to access the parameters of the method or the variables defined in the method, the arguments and variables must be decorated as final. Because although the anonymous inner class is inside the method, but actually compiles, the inner class compiles to outer.inner, which means that the internal class is located at the same level as the method in the outer class, and the variable or parameter in the method in the outer class is just a local variable of the method. The scope of these variables or parameters is valid only within this method. Because internal classes and methods are compiled at the same level, the variables or parameters in a method are only final, and inner classes can be referenced.

Java code:
Package com.cxz.j2se;

public class MyClass {
Public MyClass () {
Final int finalvalue = 10;
int not$final = 20;
MyInterface MyInterface = new MyInterface () {
public void Functionwithoutpara () {
Compile Error
System.out.println (nofinal);
System.out.println (Finalvalue);
}

public void Functionwithpara (int num) {
SYSTEM.OUT.PRINTLN ("The parameter" + num
+ "have been passed by the method");
}

};
Myinterface.functionwithoutpara ();
Myinterface.functionwithpara (not$final);
System.out.println (Myinterface.getclass (). GetName ());
}

public static void Main (string[] args) {
New MyClass ();

}

}

Second, why the local inner class can only access the final variable
In simple terms, the scope of the problem. It's as if something outside of the method doesn't change the variable defined in the method, because you don't know that the local variable is already present in the method. In this inner class, the local variables inside the method are invalidated, that is, they are not in scope, so they are not accessible.

But why is it possible to use final but accessible?
Because Java is implemented using a copy local variable, which means that a copy of the local variable defined as final is used, and the reference can be used, but it cannot be re-assigned. This creates the illusion of access local variable, which is not usually caused by the inability to re-assign values.

If you define a local inner class, and the local inner class uses an object that is defined externally, why does the compiler require that its parameter reference be final?
Note: The local inner class, including the anonymous inner class.

The reasons are as follows:

Abstract class absclass{
public abstract void print ();
}

public class test2{
public static void Test (final String s) {//Once the parameter is used inside an anonymous class, it must be final
Absclass c=new Absclass () {
public void print () {
System.out.println (s);
}
};
C.print ();
}
public static void Main (string[] args) {
Test ("Hello world!");
}
}

Each process in the JVM will have more than one root, each static variable, method parameter, local variable, and of course this refers to a reference type. The underlying type is not a root, and the root is actually a storage address. The garbage collector starts by traversing the objects it references and marking them from the root, so recursively to the nearest After all the roots have been traversed, the object description that is not tagged is not referenced, so it is the object that can be reclaimed (some objects have finalized methods, although there is no reference, However, there is a dedicated queue in the JVM that references them until the finalized method is executed to remove from the queue a truly unreferenced object that can be recycled, regardless of what is discussed in this topic, including the partitioning of generations, and so on. This looks good.

However, in the callback method of the inner class, s can neither be a static variable nor a temporary variable in the method, nor a method parameter, it cannot be a root, there is no variable in the inner class to reference it, its root is in that method outside the inner class, if the outside variable s is pointing to another object, The object s in the callback method loses its reference and may be recycled, and since the internal class callback method is mostly executed in another thread, it may also continue to be accessed after it is reclaimed. What will this result be?

Using the final modifier not only keeps the object's references from changing, but the compiler also maintains the object's lifetime in the callback method. So that's the fundamental meaning of the final and final parameters.

Why anonymous intrinsic class parameters must be final type (reprinted)

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.