Today I learned about inner classes and learned that inner classes can hold this of outer classes, so that OuterClass.this.medthod() can be used in inner classes to reference the corresponding outer class methods. But I wrote the code and it can run. However, I don't understand the calling logic very well. I hope you can enlighten me!
public class test {
public void report(){
System.out.println("I'm invoked!");
}
public void perform(){
new Speaker().handleAction(new Action(){
@Override
public void action() {
report();//???為什么能調(diào)用report??
}
});
}
public static void main(String[] args) {
new test().perform();//測(cè)試代碼
}
}
class Speaker{
void handleAction(Action act){
act.action();
}
}
interface Action{
void action();
}
The design is like this. The test object calls the perform method, which creates a new Speaker anonymous class object. The object calls its handleAction method. The parameter of this method is an Action interface, and the interface needs to override the action abstract method. I used the report method belonging to test. The output is normal.
Then I want to know, there is a local object of an anonymous class in the method of the test object, and the local object parameter is an anonymous class that implements the interface. Why can report be called in this anonymous class? Does it hold the test.this pointer?
My understanding is that new Speaker().handleAction(new Action(){....
The implementation logic here has nothing to do with test.this, and there is no need to hold test. this???
public void perform(){
new Speaker().handleAction(new Action(){
@Override
public void action() {
report();//???為什么能調(diào)用report??
}
});
}
new Speaker()
不是匿名內(nèi)部類,它有確切的類名Speakernew Action(){}
是匿名內(nèi)部類,會(huì)在編譯的時(shí)候給它一個(gè)類名(我們假定它的類名叫Test,你可以打印this.getClass()看看)
看出兩者的區(qū)別了嗎?匿名內(nèi)部類多出了個(gè){}。
由于new Action(){}
is created in the scope of the test object, so its outer class is Test.
Anonymous inner classes also have constructors, and they are a little different from the constructors of ordinary classes. When compiling, another parameter will be inserted before the parameter list of the constructor of the anonymous inner class. This parameter is a reference to the object of the outer class. Compilation The class will then look like this:
Test implements Action {
final T this public void perform(){
new Speaker().handleAction(new Test(this));
}
;
Test(T thisrrreee){
this.thisrrreee = thisrrreee;
}
@Override
public void action() {
thisrrreee.report();
}
}
new Action(){...}
Actually, Test$1 is created and the test object reference is passed to Test$1 through the constructor
So the anonymous inner class holds a reference to the outer class and can call methods of the outer class