匿名內部類的構造器

匿名內部類的構造器

  來看一個例子:html

class A{
    public B f() {
        return new B() {
            {
                setName("annoyInner");    //非靜態初始塊,等同於構造方法
            }
            //。。。
            //能夠自定義成員變量、成員方法
            //能夠重寫父類方法
        };
    }
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.f().getName());  
    }
}
class B{
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public B() {
        System.out.println("B的無參構造");
    }
}

  打印結果:性能

B的無參構造
annoyInner

  在匿名類中,可用花括號括起來進行一些必要的初始化操做,表示非靜態初始化塊,等同於構造方法。因爲沒有方法名,此構造方法不區分有參無參,那麼怎麼在匿名構造方法中使用參數呢?學習

class A{
    public B f() {
        String name = "annoyInner";
        return new B() {
            {
                setName(name);  //直接使用局部變量便可
            }
            //。。。
            //能夠自定義成員變量、成員方法
            //能夠重寫父類方法
        };
    }
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.f().getName());
    }
}
class B{
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public B() {
        System.out.println("B的無參構造");
    }
}

  打印結果同上。匿名類中直接使用局部變量或成員變量便可,至關於匿名類的有參構造器(Java 中局部內部類和匿名內部類訪問的局部變量必須由 final 修飾,以保證內部類和外部類的數據一致性。但從 Java 8 開始,添加了 Effectively final 功能,咱們能夠不加 final 修飾符,由系統默認添加。詳情可點擊《Java8新特性之Effectively final》進行學習。優化

  接下來又有個問題,匿名類的構造器能不能重載呢?this

  答案是不能,仍是由於匿名類沒有名字,連賦予參數的地方都沒有,可是你能夠這樣寫:spa

class A{
    public B f() {
        return new B() {
            {
                setName("annoyInner1");
            }
            {
                setName("annoyInner2");
            }
            {
                setName("annoyInner3");
            }
            //...
        };
    }
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.f().getName());
    }
}

  打印結果是annoyInner3,這至關因而多個初始化塊,會依次執行,並非構造器的重載,可是這樣寫跟寫在一個初始化塊中沒有什麼區別。.net

  咱們都知道匿名類實例化時會默認調用父類的無參構造,如何調用父類的有參構造?加上super(name)是不行的:code

class A{
    public B f() {
        return new B("annoyInner") {
            {
                //super(name);  //編譯報錯
            }
        };
    }
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.f().getName());
    }
}
class B{
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public B() {
        System.out.println("B的無參構造");
    }
    public B(String name) {
        this.name = name;
        System.out.println("B的有參構造");
    }
}

  打印結果以下,直接在匿名類的表達式中使用父類的有參構造便可htm

B的有參構造
annoyInner

   下面是一個很常見的匿名類的運用,常常看見有人這麼寫:blog

             ArrayList<String> list = new ArrayList<String>() {{
                add("A");
                add("B");
                add("C");
            }};

            Map m = new HashMap() {
                {
                    put("name","zhangsan");
                    put("age",18);
                }
            };

   看到這個,我只想說:

  花裏胡哨!!!

  拿arrayList爲例,外層的花括號建立了一個繼承於ArrayList的匿名類,裏層的花括號表示在這個匿名類的初始化塊中調用了繼承而來的add方法,實際上這個匿名類和ArrayList沒有什麼區別。這樣寫好像是簡潔了一些,可是可讀性也要差一些,也並不會帶來多少性能上的優化,目前本人還不知道會不會引起什麼問題。不過取決於我的喜愛,用用也無妨。

相關文章
相關標籤/搜索