天天看點

java 匿名内部類 Anonymous Classes

1、簡介

匿名類是一個沒有類名的特殊内部類,也叫做匿名内部類。匿名内部類适合建立隻需要使用一次的類。建立匿名内部類時須繼承一個已有的父類或實作一個接口。由于匿名類本身無名,是以也就不存在構造方法,而且匿名類不能重複使用。

具體可以參考

Anonymous Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects) (oracle.com)

2、定義匿名内部類

本地類是類聲明,而匿名類是表達式,這意味着可以在另一個表達式中定義該類。

匿名類本身沒有名字,在建立的時候用new語句的一部分來聲明。格式如下:

new父類名/接口名{
    //類
}      

例如:

package com.atguigu.java;

class HelloWorldAnonymousClasses {

    interface HelloWorld {
        public void greet();
        public void greetSomeone(String someone);
    }

    public void sayHello() {
        // 局部類實作HelloWorld接口
        class EnglishGreeting implements HelloWorld {
            String name = "world";
            public void greet() {
                greetSomeone("world");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hello " + name);
            }
        }

        HelloWorld englishGreeting = new EnglishGreeting();

        // 匿名類實作HelloWorld接口
        HelloWorld spanishGreeting = new HelloWorld() {
            String name = "mundo";
            public void greet() {
                greetSomeone("mundo");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hola, " + name);
            }
        };
        englishGreeting.greet();
        spanishGreeting.greet();
    }

    public static void main(String... args) {
        HelloWorldAnonymousClasses myApp = new HelloWorldAnonymousClasses();
        myApp.sayHello();
    }
}      

3、匿名内部類的文法

如前所述,匿名類是一種表達式。匿名類表達式的文法就像構造器的調用,但代碼塊中包含類定義。

實作接口的匿名類

public class Test {
    public static void main(String[] args) {
        MyInterface mi = new MyInterface() {
            @Override
            public void say() {
                System.out.println("實作接口 hello");
            }
        };
        mi.say();
    }
}

interface MyInterface{
    void say();
}      

繼承父類的匿名子類

public class Test {
    public static void main(String[] args) {
        // 多态:父類類型的變量指向子類類型的對象,調用方法的時候,是調用子類的實作(子類重寫、實作)
        MyClass mc = new MyClass("subclass"){
            public void hello(){
                System.out.println(name+",匿名子類問好");
            }
        };
        mc.hello();
    }
}

class MyClass{
    public String name;

    public MyClass(String name) {
        this.name = name;
    }
    public void hello(){
        System.out.println("hello");
    }
}      

從上面可以看出,匿名類表達式包括以下内容:

  • 操作符 new

  • 要實作的接口名稱或要擴充的類的名稱。
  • 包含構造器參數的括号,就像正常的類執行個體建立表達式一樣。注意:當實作接口時,沒有構造器,是以使用空的括号,如果是匿名子類,與執行個體化普通類的文法類似。
  • 一個主體{}。
  • 匿名類的聲明是一個表達式,是語句的一部分,以分号結尾。

通路作用域内的局部變量、定義和通路匿名内部類成員

與局部類一樣,匿名類可以捕獲變量:它們具有相同的通路封閉範圍的局部變量:

  • 匿名類可以通路其外部類的成員。
  • 匿名類無法通路其外部類未聲明為或有效最終的本地變量。(注意:JDK1.8即使沒有用final修飾也可以通路)
  • 與嵌套類一樣,匿名内部類定義的類型(如變量)會屏蔽其作用域範圍内的其他同名類型(變量)。

匿名内部類對其成員也有與本地類相同的限制:

  • 不能在匿名類中聲明靜态屬性和方法。
  • 匿名類可以具有靜态成員,前提是它們是常量。

請注意,您可以在匿名類中聲明以下事項:

  • 字段
  • 額外方法(父接口、類中沒有的方法)
  • 執行個體初始化器