Java 匿名內部類

來源:互聯網
上載者:User

標籤:

Java 匿名內部類

前邊一篇文章對匿名內部類做了一個簡單的瞭解,http://my.oschina.net/xinxingegeya/blog/297004。這篇文章來深入的瞭解一下匿名內部類的使用


Java匿名類中的this

ava的匿名類特性,在於可以在項目裡“內聯”地實現一個類型,它可以繼承一個現有的具體或抽象類別,或是實現介面,並提供完整的成員實現。例如,這裡有個抽象類別,定義了一個抽象方法:

// Javaabstract class MyAbstractClass {    String getName() {        return "MyAbstractClass";    }    abstract void print();}

然後我們在另一個地方使用一個匿名類,繼承這個類:

// Javaclass MyClass {    String getName() {        return "MyClass";    }    MyAbstractClass someMethod() {        return new MyAbstractClass() {            public void print() {                System.out.println(getName());            }        };    }}

好,現在提一個問題,運行下面這行代碼會列印出什麼結果?

// Javanew MyClass().someMethod().print();

輸出結果是MyAbstractClass而不是MyClass。換句話說,匿名型別中調用的getName方法是定義在MyAbstractClass裡的,而不是定義在詞法範圍(Lexical Scope)裡的getName方法。根據Java規範,匿名類中的this(包括上面代碼中“隱式”的this)表示類型本身對象,而與上下文無關。如果要訪問詞法範圍裡的getName方法(即MyClass的方法),則反而必須顯式指定MyClass類 ,例如:

// Javaclass MyClass {    String getName() {        return "MyClass";    }    MyAbstractClass someMethod() {        return new MyAbstractClass() {            public void print() {                System.out.println(MyClass.this.getName());            }        };    }}


匿名內部類定義屬性欄位

如下是匿名內部類的例子,

package com.usoft.java;/** */public interface CallBack {    void call();}
package com.usoft.java;/** * @author: Lenovo(2015-08-09 16:00) */public class Test {    private final Integer c = 12;    private Integer a;    private Integer b;    public Test(Integer a, Integer b) {        this.a = a;        this.b = b;    }    public static void main(String args[]) {        Test test = new Test(1, 2);        test.test(true);    }    public void hello(CallBack back) {        back.call();    }    public void test(final boolean flag) {        System.out.println("test");        hello(new CallBack() {            private Integer ia = a;            private Integer ib = b;            @Override            public void call() {                System.out.println("callback");                if (flag)                    System.out.println(ia + ib + c);                else                    System.out.println(ia + ib + c + 1);            }        });    }}

匿名內部類雖然說是匿名,但編譯後也是有名字的。看一下匿名內部類的反編譯結果,類的名字是 Test$1,和普通的類沒有什麼區別。

C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft\java>javap -p Test$1.classCompiled from "Test.java"class com.usoft.java.Test$1 implements com.usoft.java.CallBack {  private java.lang.Integer ia;  private java.lang.Integer ib;  final boolean val$flag;  final com.usoft.java.Test this$0;  com.usoft.java.Test$1(com.usoft.java.Test, boolean);  public void call();}

在匿名內部類中定義了兩個屬性 ia 和 ib,ia 和 ib 的初始化和賦值是在匿名內部類的建構函式中完成的,值是外部類中a 和 b。在匿名內部類中使用了外部的變數 flag。

其中初始化和賦值 ia 和 ib的時候更明顯和更好理解的寫法是,

public void test(final boolean flag) {    System.out.println("test");    hello(new CallBack() {        private Integer ia = Test.this.a;        private Integer ib = Test.this.b;        @Override        public void call() {            System.out.println("callback");            if (flag)                System.out.println(ia + ib + c);            else                System.out.println(ia + ib + c + 1);        }    });}

運行結果,

test

callback

15


匿名內部類的初始化

由於匿名內部類沒有建構函式(通過反編譯你可以知道是有建構函式的),那麼怎麼初始化匿名內部類,下面是一種方法,

public void test(final boolean flag) {    System.out.println("test");    hello(new CallBack() {        private Integer ia = Test.this.a;        private Integer ib = Test.this.b;        {            ia = 3;            ib = 4;        }        @Override        public void call() {            System.out.println("callback");            if (flag)                System.out.println(ia + ib + c);            else                System.out.println(ia + ib + c + 1);        }    });}

通過代碼塊,可以初始化類的屬性,列印的結果為 19;


為什麼使用final

通過上面的反編譯結果,我們可以看到,內部類的建構函式(位元組碼層面)中有一個外部類參數,同時內部類中有一個外部類的引用,當使用外部類的屬性時,是通過外部類的引用得到的相應的屬性值。如果外部類的屬性引用改變,那麼內部類和外部類狀態就不統一了。所以為了狀態的統一,規定所有的外部類的屬性為final定義,即不可改變的引用。

private final Integer c = 12; // 必須為final


匿名內部類的使用總結
  1. 使用匿名內部類時,我們必須是繼承一個類或者實現一個介面,但是兩者不可兼得,同時也只能繼承一個類或者實現一個介面。

  2. 匿名內部類中是不能定義建構函式的。

  3. 匿名內部類中不能存在任何的靜態成員變數和靜態方法。

  4. 匿名內部類為局部內部類,所以局部內部類的所有限制同樣對匿名內部類生效。

  5. 匿名內部類不能是抽象的,它必須要實現繼承的類或者實現的介面的所有抽象方法。

參考引用:http://www.cnblogs.com/chenssy/p/3390871.html

http://blog.zhaojie.me/2011/06/java-anonymous-method-closure-scope-this.html

=======================END=======================

Java 匿名內部類

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.