搜尋

首頁  >  問答  >  主體

oop - Java中,關於匿名內部類別呼叫外部類別方法的疑惑

今天學習了內部類別的知識,知道內部類別是可以持有外部類別的this,從而在內部類別中可以使用OuterClass.this.medthod()來引用對應外部類別方法。但是我寫出下程式碼,可以運行,然而其中的呼叫邏輯我不是很明白,望賜教!

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();//???为什么能调用report??
                }
                
            });
        }
        public static void main(String[] args) {
            new test().perform();//测试代码
        }
        
    }
    class Speaker{
        void handleAction(Action act){
            act.action();
        }
    }
    interface Action{
        void action();
    }

其中設計是這樣的,test對象調用perform方法,該方法其中新建一個Speaker匿名類對象,該對象調用了其handleAction方法,該方法的參數是一個Action接口,接口需要重寫action抽象方法。我使用了屬於test的report方法。輸出是正常的。

那麼我想知道,test對象的方法中有一個匿名類的局部對象,局部對象參數是一個實現接口的匿名類,為什麼在這個匿名類中可以調用report?它持有test.this指針嗎?
我理解中,new Speaker().handleAction(new Action(){....這裡面的實作邏輯和test.this一點關係都沒有,也沒有必要持有test. this???

漂亮男人漂亮男人2789 天前1057

全部回覆(1)我來回復

  • PHP中文网

    PHP中文网2017-05-17 10:09:37

            public void perform(){
                new Speaker().handleAction(new Action(){
                    @Override
                    public void action() {
                        report();//???为什么能调用report??
                    }
                });
            }

    new Speaker()不是匿名内部类,它有确切的类名Speaker
    new Action(){}是匿名内部类,会在编译的时候给它一个类名(我们假定它的类名叫Test,你可以打印this.getClass()看看)
    看出两者的区别了吗?匿名内部类多出了个{}。
    由于new Action(){}是在test物件的作用域裡被建立的,所以它的外部類別是Test。

    匿名內部類別也有建構器,而且和普通類別的建構器有點不一樣,編譯的時候會在匿名內部類別的建構器的參數列表之前再插入一個參數,這個參數是外部類別的物件的引用,編譯之後這個類長這樣:

    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(){...}其實是創建了Test$1,並且透過建構器把test物件引用傳給Test$1

    rrreee

    所以匿名內部類別持有外部類別的引用,並且可以呼叫外部類別的方法

    回覆
    0
  • 取消回覆