首頁 Java java教程 詳解匿名內部類

詳解匿名內部類

Dec 15, 2016 pm 12:29 PM
匿名內部類別

      在Java提高篇-----詳解內部類別中對匿名內部類別做了一個簡單的介紹,但是內部類別還存在很多其他細節問題,所以就衍生出這篇部落格。在這篇部落格中你可以了解到匿名內部類別的使用、匿名內部類別要注意的事項、如何初始化匿名內部類別、匿名內部類別使用的形參為何要為final。


       一、使用匿名內部類內部類

        建立格式如下:

new 父类构造器(参数列表)|实现接口()    
    {    
     //匿名内部类的类体部分    
    }
登入後複製

       在這裡我們看到使用匿名內部類別我們必須要繼承一個父類別或實作一個接口,當然也只能只繼承一個父類別或實作一個介面。同時它也是沒有class關鍵字,這是因為匿名內部類別是直接使用new來產生一個物件的參考。當然這個引用是隱性的。

public abstract class Bird {  
    private String name;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
      
    public abstract int fly();  
}  
  
public class Test {  
      
    public void test(Bird bird){  
        System.out.println(bird.getName() + "能够飞 " + bird.fly() + "米");  
    }  
      
    public static void main(String[] args) {  
        Test test = new Test();  
        test.test(new Bird() {  
              
            public int fly() {  
                return 10000;  
            }  
              
            public String getName() {  
                return "大雁";  
            }  
        });  
    }  
}  
------------------  
Output:  
大雁能够飞 10000米
登入後複製

       在Test類別中,test()方法接受一個Bird型別的參數,同時我們知道一個抽象類別是沒有辦法直接new的,我們必須先有實作類別才能new出來它的實作類別實例。所以在mian方法中直接使用匿名內部類別來建立一個Bird實例。

       由於匿名內部類別不能是抽象類別,所以它必須實現它的抽象父類別或介面裡面所有的抽象方法。

     收到

       對於匿名內部類別的使用它是存在一個缺陷的,就是它只能被使用一次,創建匿名內部類別時它會立即創建一個該類別的實例,該類別的定義會立即消失,所以匿名內部類別是不能夠被重複使用。對於上面的實例,如果我們需要對test()方法裡面內部類別進行多次使用,建議重新定義類別,而不是使用匿名內部類別。


       二、注意事項

       在使用匿名內部類別的過程中,因此我們需要注意如同一個點:

?者不可兼得,同時也只能繼承一個類別或實作一個介面。

      2、匿名內部類別中是無法定義建構子的。

      3、匿名內部類別中不能有任何的靜態成員變數與靜態方法。

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

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

       三、使用的形參為何要為final

       我們給予匿名類傳遞參數的時候,且該形參在內部類別中若要使用,那麼內部類別若為匿名類別。也就是說:當所在的方法的形參需要被內部類別裡面使用時,該形參必須為final。

      為什麼必須為final呢?

      首先我們知道在內部類別編譯成功後,它會產生一個class文件,該class文件與外部類別並不是同一class文件,僅僅只保留對外部類別的引用。當外部類別傳入的參數需要被內部類別呼叫時,從java程式的角度來看是直接被呼叫:

public class WildGoose extends Bird{  
    public int fly() {  
        return 10000;  
    }  
      
    public String getName() {  
        return "大雁";  
    }  
}  
  
WildGoose wildGoose = new WildGoose();  
test.test(wildGoose);
登入後複製

從上面程式碼看好像name參數應該是被內部類別直接呼叫?其實不然,在java編譯之後實際的操作如下:

public class OuterClass {  
    public void display(final String name,String age){  
        class InnerClass{  
            void display(){  
                System.out.println(name);  
            }  
        }  
    }  
}
登入後複製

       所以從上面程式碼來看,內部類別並不是直接呼叫方法傳遞的參數,而是利用自身的構造器對傳入的參數進行備份,自己內部方法呼叫的實際上時自己的屬性而不是外部方法傳遞進來的參數。

直到这里还没有解释为什么是final?在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。

简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。

故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。


四、匿名内部类初始化

我们一般都是利用构造器来完成某个实例的初始化工作的,但是匿名内部类是没有构造器的!那怎么来初始化匿名内部类呢?使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果。

public class OutClass {  
    public InnerClass getInnerClass(final int age,final String name){  
        return new InnerClass() {  
            int age_ ;  
            String name_;  
            //构造代码块完成初始化工作  
            {  
                if(0 < age && age < 200){  
                    age_ = age;  
                    name_ = name;  
                }  
            }  
            public String getName() {  
                return name_;  
            }  
              
            public int getAge() {  
                return age_;  
            }  
        };  
    }  
      
    public static void main(String[] args) {  
        OutClass out = new OutClass();  
          
        InnerClass inner_1 = out.getInnerClass(201, "chenssy");  
        System.out.println(inner_1.getName());  
          
        InnerClass inner_2 = out.getInnerClass(23, "chenssy");  
        System.out.println(inner_2.getName());  
    }  
}
登入後複製


更多详解匿名内部类相关文章请关注PHP中文网!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Java 匿名內部類別如何解決記憶體洩漏問題? Java 匿名內部類別如何解決記憶體洩漏問題? May 01, 2024 pm 10:30 PM

匿名內部類別可導致記憶體洩漏,問題在於它們持有外部類別的引用,從而阻止外部類別被垃圾回收。解決方法包括:1.使用弱引用,當外部類別不再被強引用持有時,垃圾回收器會立即回收弱引用物件;2.使用軟引用,垃圾回收器會在進行垃圾回收時需要記憶體時才回收軟引用物件。在實戰中,例如Android應用程式中,可以透過使用弱引用來解決因匿名內部類別引起的記憶體洩漏問題,從而在不需要監聽器時回收匿名內部類別。

Java 匿名內部類別的設計模式有哪些? Java 匿名內部類別的設計模式有哪些? May 02, 2024 pm 04:42 PM

匿名內部類別是Java中沒有明確名稱、透過new表達式創建的特殊內部類,主要用於實作特定介面或擴展抽象類,並在創建後立即使用。常見的匿名內部類別設計模式包括:適配器模式:將一個介面轉換為另一個介面。策略模式:定義和替換演算法。觀察者模式:註冊觀察者並處理事件。它在實際應用中非常有用,例如按字串長度排序TreeSet、建立匿名執行緒等。

Java 匿名內部類別在哪些場景下不適合使用? Java 匿名內部類別在哪些場景下不適合使用? May 03, 2024 pm 05:42 PM

匿名內部類別不適合使用的情況有:需要存取私有成員需要多個實例需要繼承需要存取泛型類型

Java 匿名內部類別有哪些優勢? Java 匿名內部類別有哪些優勢? Apr 30, 2024 am 11:39 AM

匿名內部類別在Java中作為方便建立子類別、簡化程式碼和處理事件(例如按鈕點擊)的特殊內部類別。實戰案例包括:事件處理:使用匿名內部類別為按鈕新增點選事件監聽器。資料轉換:使用Collections.sort方法和匿名內部類別作為比較器對集合進行排序。

Java 匿名內部類別有哪些常見錯誤? Java 匿名內部類別有哪些常見錯誤? May 02, 2024 am 09:03 AM

匿名內部類別使用錯誤:在非線程安全環境中使用捕獲未聲明的異常訪問超出範圍的變量

Java 匿名內部類別有哪些限制? Java 匿名內部類別有哪些限制? May 01, 2024 pm 02:18 PM

匿名內部類別的限制包括:無法存取外部局部變數;無法直接存取外部this引用;無法拋出checked異常;程式碼冗餘;無法序列化。

Java 匿名內部類別如何優化效能? Java 匿名內部類別如何優化效能? May 02, 2024 am 08:48 AM

匿名內部類別的效能問題在於每次使用都會重新創建,可透過以下策略最佳化:1.將匿名內部類別儲存在局部變數中;2.使用非靜態內部類別;3.使用lambda表達式。實戰測試顯示lambda表達式最佳化效果最佳。

Java 匿名內部類別如何應用於執行緒? Java 匿名內部類別如何應用於執行緒? May 02, 2024 pm 01:57 PM

匿名內部類別可簡化多執行緒程式碼的創建,無需命名,支援即時定義和使用執行緒類別。主要優勢在於簡化程式碼,而限制是無法擴展。在需要快速建立一兩個執行緒時使用,保持程式碼簡短,如果需要更複雜的邏輯,應建立單獨的類別檔案。

See all articles