2010-04-04 19 views
32

Ho avuto un'intervista giorni fa e ho lanciato una domanda come questa.come parametro del metodo in Java

Q: Invertire una lista concatenata. Viene fornito il seguente codice:

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

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

    } 
} 

Ero confuso perché non sapevo che un oggetto di interfaccia potesse essere usato come parametro di metodo. L'intervistatore ha spiegato un po 'ma non sono ancora sicuro di questo. Qualcuno potrebbe illuminarmi?

risposta

52

Questo è in effetti uno dei modi più comuni e utili per utilizzare un'interfaccia. L'interfaccia definisce un contratto e il tuo codice può funzionare con qualsiasi classe che implementa l'interfaccia, senza dover conoscere la classe concreta - può persino funzionare con classi che non esistevano ancora quando il codice è stato scritto.

Ci sono molti esempi nell'API standard Java, specialmente nel framework delle collezioni. Ad esempio, Collections.sort() può ordinare qualsiasi cosa che implementa l'interfaccia List (non solo ArrayList o LinkedList, se si trattasse dell'applicazione la propria List è raro) e il cui contenuto implementare l'interfaccia Comparable (non solo String o le classi wrapper numerici - e avere la propria classe implementare Comparable per quello scopo è piuttosto comune).

+0

Grazie Mike! L'esempio di elenco è davvero istruttivo e facile da capire. – zihaoyu

6

L'argomento richiede un oggetto, che classe implementa un'interfaccia (il parametro).

In pseudo Java codice:

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

è uguale a:

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

nota; leggi di più sulle interfacce qui: http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html

+8

Il parametro * * è un tipo di interfaccia, l'argomento * * è un oggetto skaffman

+3

E per essere veramente molto un pedent. L'argomento è un riferimento a un oggetto:} –

+0

+1 per il collegamento tutorial cogent. – trashgod

19

Non è l'interfaccia "oggetto" che viene passata al metodo, ancora solo un oggetto regolare. È solo un modo per dire "questo parametro accetterà qualsiasi oggetto che supporti questa interfaccia". È equivalente all'accettazione di alcuni oggetti di un tipo di classe base, anche se stai passando in una sottoclasse.

+0

Ottimo, aiutato !! : D – roottraveller

7

Si chiama programmazione di interfacce. Non si codifica in una specifica classe di implementazione di elenchi di nodi ma nell'interfaccia implementata da tutte quelle implementazioni.

In questo modo il codice funzionerà ancora se qualcuno scrive un'implementazione nuova e molto migliore di NodeList dopo aver scritto il metodo inverso e non è necessario adattare il codice per ogni nuova implementazione di NodeList.

1

Il vantaggio principale dell'utilizzo delle interfacce, IMHO, è la possibilità di eseguire facilmente i test. Supponiamo di avere un'interfaccia chiamata PatientManager.

È possibile scrivere test di unità specifici per cose immaginabili come "CachingPatientManager" o "LDAPPatientManager", il caso d'uso potrebbe essere una miriade.

Il vantaggio è che la programmazione dell'interfaccia diventa altamente riutilizzabile e verificabile.

1

Non è possibile creare un'istanza (/ oggetto) di un'interfaccia. Sì, è possibile passare all'interfaccia come parametro nella funzione. Ma la domanda sembra incompleta.L'interfaccia non è implementata da nessuna classe. Manca qualcosa. Se si tenta di eseguire questo, il compilatore non mostrerà alcun errore.

Tuttavia, nel metodo reverse() è necessario creare un'istanza di classe che implementa l'interfaccia NodeList. Spero che abbia senso.

0

Questa è una possibile implementazione:

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()); 
     } 
} 

output del programma:

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

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

Sono molto curioso di sapere se questo problema può essere risolto utilizzando una classe anonima. Qualche idea?

0

Aveva questa stessa confusione mentre imparava la roba lambda. Questo video non ha spiegato il concetto, ma è un modo chiaro per vedere come funziona in termini di passaggio di un'interfaccia come parametro.

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

Problemi correlati