1. 程式人生 > >[Java基礎]介面能否被例項化以及匿名內部類

[Java基礎]介面能否被例項化以及匿名內部類

首先回答我們標題中的問題,介面能否被例項化呢?
答案是顯而易見的,不能!

下面我們考慮如下的程式碼:

Runnable r1 = new Runnable(){

       @Override
       public void run(){
         System.out.println("Hello world one!");
       }
     };

我們知道Runnable是一個介面而非一個類,它只含有一個抽象方法run(),它既沒有構造方法也不能被例項化。那麼它為什麼可以被new關鍵字修飾呢?這對於作者這種初學者來說是一個難以理解的問題。

那麼理解它的關鍵就在一個關鍵的知識點上–匿名內部類

。匿名內部類的存在使得開發者可以在不需要另寫一個介面的實現類的情況下,達到實現一個介面的目的。我們以如下程式碼塊來解釋以上的說法:

public interface Runnable {
    public void run();
}
public class TestRunnable implements Runnable {
    public void run() {
        ......
    }

    public static void main(String args[]) {
        TestRunnable tr1 = new TestRunnable(); 
        tr1.run();
    }
}

其實後者和前者的程式碼達到了相同的目的–及實現了一個介面,並呼叫了介面中的方法。只不過匿名內部類省去了我們新建一個實現類的步驟。那麼結論顯而易見,在程式碼塊1中,new Runnable() {}實際上並沒有例項化Runnable介面,而是建立了一個實現了Runnable介面的匿名內部類,從而達到呼叫run()的目的。

ps. 理解了匿名內部類,我們實際上就理解了匿名內部類的存在就是為了簡化步驟,提高開發效率。因為沒有人願意僅僅為了實現一個接口裡的方法就大費周章的為它單獨寫一個實現類。進一步的,在JDK 1.8中介紹了又一新特性lambda expression,利用它可以進一步簡化以上的程式碼,如下:

 6 public class RunnableTest {
 7   public static void main(String[] args) {
 8     
 9     System.out.println("=== RunnableTest ===");
10     
11     // Anonymous Runnable
12     Runnable r1 = new Runnable(){
13       
14       @Override
15       public void run(){
16         System.out.println("Hello world one!");
17       }
18     };
19     
20     // Lambda Runnable
21     Runnable r2 = () -> System.out.println("Hello world two!");
22     
23     // Run em!
24     r1.run();
25     r2.run();
26     
27   }
28 }

通過對比一眼便可以看出,通過lambda expression的方式,幾行程式碼被縮減到了僅僅一行,多麼簡潔,實用的語法啊。更多關於lambda的描述,請參見文末給出的官方文件。

引用: