匿名內部類的構造器


匿名內部類的構造器

  來看一個例子:

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》進行學習。

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

  答案是不能,還是因為匿名類沒有名字,連賦予參數的地方都沒有,但是你可以這樣寫:

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,這相當於是多個初始化塊,會依次執行,並不是構造器的重載,但是這樣寫跟寫在一個初始化塊中沒有什么區別。

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

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的有參構造");
    }
}

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

B的有參構造
annoyInner

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

             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沒有什么區別。這樣寫好像是簡潔了一些,但是可讀性也要差一些,也並不會帶來多少性能上的優化,目前本人還不知道會不會引發什么問題。不過取決於個人喜好,用用也無妨。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM