2010-04-04 64 views
32

我在幾天前接受了一次採訪,並且引發了一個像這樣的問題。作爲Java中的方法參數的接口

問:反轉鏈表。下面的代碼是給定:

public class ReverseList { 
    interface NodeList { 
     int getItem(); 
     NodeList nextNode(); 
    } 
    void reverse(NodeList node) { 

    } 
    public static void main(String[] args) { 

    } 
} 

我很困惑,因爲我不知道一個接口對象可以作爲一個方法的參數沒有。面試官解釋了一點,但我仍然不確定這一點。有人能給我啓發嗎?

回答

52

這實際上是使用界面最常用和最實用的方法之一。接口定義了一個契約,你的代碼可以與任何實現接口的類一起工作,而不需要知道具體的類 - 它甚至可以處理編寫代碼時尚不存在的類。

Java標準API中有很多例子,尤其是在集合框架中。例如,Collections.sort()可以排序任何實現的List接口(不只是ArrayListLinkedList,雖然實現自己的List是罕見的),其內容落實Comparable接口(不只是String或數值包裝類 - 和擁有自己的類實現Comparable爲此目的是相當共同)。

+0

謝謝邁克!列表示例非常有啓發性,易於理解。 – zihaoyu 2010-04-05 18:00:47

6

參數需要一個對象,該類實現一個接口(參數)。

的Java的代碼:

void reverse(NodeList node) { 
    // your code 
} 

等於:

reverse(x) { 
    if(x == null || x instanceof NodeList) { 
     // your code 
    }else throw new RuntimeException("Some sort of error."); 
} 

注;在這裏閱讀更多接口:http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html

+8

的*參數*是一個接口類型,*參數*是一個對象 skaffman 2010-04-04 18:28:49

+3

和以真的太大的pedent。該參數是對對象的引用:} – 2010-04-04 20:15:00

+0

對於有說服力的教程鏈接。 – trashgod 2010-04-04 22:24:04

19

這不是接口「對象」被傳遞給該方法,仍然只是一個常規的對象。這只是一種說法,「這個參數將接受任何支持此接口的對象」。這相當於接受基類類型的某個對象,即使您傳遞的是子類。

+0

太棒了,幫助! :D – roottraveller 2017-06-14 12:19:46

7

這被稱爲接口編程。您不會編碼到特定的節點列表實現類,而是編碼到所有這些實現實現的接口。

這樣,如果有人在編寫逆向方法後寫了一個新的更好的NodeList實現,並且不必爲每個NodeList的新實現調整代碼,那麼代碼仍然可以工作。

1

使用接口,恕我直言,主要優勢是能夠輕鬆測試。假設您有一個名爲PatientManager的接口。

你可以爲「CachingPatientManager」或「LDAPPatientManager」等可想象的東西編寫特定的單元測試,用例可能無數。

好處是因爲接口編程變得高度可重用和可測試。

1

您無法創建接口的實例(/對象)。 是的,您可以將Interface作爲參數傳遞給函數。但這個問題似乎並不完整。接口不是由任何類實現的。缺了點什麼。如果你嘗試運行這個,編譯器不會顯示任何錯誤。

但是,在reverse()方法中,您需要創建一個實現NodeList接口的類的實例。我希望這是有道理的。

0

這是一個可能的實現:

public class ReverseList { 
interface NodeList { 
    int getItem(); 
    NodeList nextNode(); 
} 

static class Node implements NodeList { 
    private int item; 
    private Node next; 

    @Override 
    public int getItem() { 
     return item; 
    } 

    public void setItem(int si) { 
     item = si; 
    } 

    @Override 
    public NodeList nextNode() { 
     return this.next; 
    } 

    public void setNext(Node n) {this.next=n;} 

} 

Node reverse(NodeList head) { 
    Node node = (Node) head; 
    Node previous = null; 
    while(node.nextNode() !=null) { 
     Node tempNext = (Node) node.nextNode(); 
     node.setNext(previous); 
     previous = node; 
     node = tempNext; 
    } 
    node.setNext(previous); 
    return node; 

} 
public static void main(String[] args) { 
    //Initialization block 
    ReverseList rl = new ReverseList(); 
    Node n1= new Node(); n1.setItem(1); 
    Node n2=new Node(); n2.setItem(2); 
    Node n3 =new Node(); n3.setItem(3); 
    n1.setNext(n2); n2.setNext(n3); n3.setNext(null); 

    //Reversing the list 
    System.out.println("Before reversal");  
    System.out.println(n1.getItem() +"->" 
        + n1.nextNode().getItem() + "->" 
        + n1.nextNode().nextNode().getItem() + "->" 
        +n1.nextNode().nextNode().nextNode()); 


    rl.reverse(n1); 

    System.out.println("\nAfter reversal"); 
    System.out.println(n3.getItem() +"->" 
      + n3.nextNode().getItem() + "->" 
      + n3.nextNode().nextNode().getItem() + "->" 
      +n3.nextNode().nextNode().nextNode()); 
     } 
} 

程序輸出:

Before reversal 
1->2->3->null 

After reversal 
3->2->1->null 

我很好奇,想知道這個問題可以通過使用匿名類來解決。有任何想法嗎?

0

在學習lambda的時候也有同樣的困惑。 這個視頻並沒有解釋這個概念,但它是一個清楚的方式,讓你看看它是如何在接口作爲參數傳遞方面的工作。

https://www.youtube.com/watch?v=mk3erzL70yM