interface als Methodenparameter in Java

Lesezeit: 4 Minuten

Benutzer-Avatar
zihaoyu

Ich hatte vor Tagen ein Vorstellungsgespräch und bekam eine Frage wie diese.

F: Kehren Sie eine verkettete Liste um. Folgender Code ist gegeben:

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

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

    }
}

Ich war verwirrt, weil ich nicht wusste, dass ein Schnittstellenobjekt als Methodenparameter verwendet werden kann. Der Interviewer hat es ein bisschen erklärt, aber ich bin mir immer noch nicht sicher. Könnte mich jemand aufklären?

  • Laut Java-Champion Ben Evans bei Red Hat „erlaubt Java nur zwei Arten von Werten: primitive Typen und Objektreferenzen“, und da Schnittstellen keine primitiven sind, und weil reverse() akzeptiert einen formalen Parameter (aus dem formalen Argument des Aufrufers) eines Schnittstellentyps NodeListdann reverse() akzeptiert eine Objektreferenz, keine Schnittstelle. Sie können dies bestätigen, indem Sie sich den Bytecode ansehen, wo Sie sehen würden invokeinterface als Teil einer vtable-Analyse, die eine dynamische Methodenzuteilung implementiert. Sehen blogs.oracle.com/javamagazine/post/…

    – zartgelb

    10. Juni um 20:03 Uhr


Benutzer-Avatar
Michael Borgwart

Dies ist in der Tat eine der gebräuchlichsten und nützlichsten Arten, eine Schnittstelle zu verwenden. Die Schnittstelle definiert einen Vertrag, und Ihr Code kann mit jeder Klasse arbeiten, die die Schnittstelle implementiert, ohne die konkrete Klasse kennen zu müssen – er kann sogar mit Klassen arbeiten, die noch nicht existierten, als der Code geschrieben wurde.

Es gibt viele Beispiele in der Java-Standard-API, insbesondere im Collections-Framework. Zum Beispiel, Sammlungen.sort() kann alles sortieren, was das implementiert List Schnittstelle (nicht nur ArrayList oder LinkedListobwohl Sie Ihre eigenen implementieren List ist ungewöhnlich) und deren Inhalte implementieren die Comparable Schnittstelle (nicht nur String oder die numerischen Wrapper-Klassen – und Ihre eigene Klassenimplementierung haben Comparable dafür ist ziemlich gemeinsames).

  • Danke Mike! Listenbeispiel ist wirklich lehrreich und leicht zu verstehen.

    – zihaoyu

    5. April 2010 um 18:00 Uhr

Es ist nicht das “Objekt” der Schnittstelle, das an die Methode übergeben wird, sondern nur ein normales Objekt. Es ist nur eine Art zu sagen “dieser Parameter akzeptiert jedes Objekt, das diese Schnittstelle unterstützt”. Es ist gleichbedeutend mit dem Akzeptieren eines Objekts eines Basisklassentyps, selbst wenn Sie eine Unterklasse übergeben.

  • Super, geholfen!! 😀

    – Wurzelreisender

    14. Juni 2017 um 12:19 Uhr

Benutzer-Avatar
äh

Dies wird als Programmieren von Schnittstellen bezeichnet. Sie codieren nicht für eine bestimmte Implementierungsklasse von Knotenlisten, sondern für die Schnittstelle, die von all diesen Implementierungen implementiert wird.

Auf diese Weise funktioniert Ihr Code immer noch, wenn jemand eine neue und viel bessere Implementierung von schreibt NodeList nachdem Sie Ihre umgekehrte Methode geschrieben haben und Sie Ihren Code nicht für jede neue Implementierung von anpassen müssen NodeList.

  • Innen reverse() wir können nicht direkt weiterarbeiten node dem wir vielmehr eine Instanz einer implementierenden Klasse zuweisen müssen NodeList. Schließlich müssen wir an einem konkreten Objekt arbeiten.

    – Billal Begueradj

    5. August 2018 um 9:25 Uhr

Benutzer-Avatar
Pindatjuh

Das Argument benötigt ein Objekt, dessen Klasse eine Schnittstelle (den Parameter) implementiert.

Im Pseudo- Java-Code:

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

ist gleich:

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

Notiz; Lesen Sie hier mehr über Schnittstellen: http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html

Dies ist eine mögliche Implementierung:

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

Programmausgabe:

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

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

Ich bin sehr neugierig zu wissen, ob dieses Problem durch die Verwendung einer anonymen Klasse gelöst werden kann. Irgendwelche Ideen?

Benutzer-Avatar
Yoho

Hatte die gleiche Verwirrung, als ich Lambda-Sachen lernte. Dieses Video hat das Konzept nicht erklärt, aber es ist eine klare Möglichkeit für Sie zu sehen, wie es in Bezug auf die Übergabe einer Schnittstelle als Parameter funktioniert.

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

Benutzer-Avatar
Nirmal

Der Hauptvorteil der Verwendung von Schnittstellen besteht meiner Meinung nach darin, einfach testen zu können. Angenommen, Sie haben eine Schnittstelle namens PatientManager.

Sie können spezifische Unit-Tests für vorstellbare Dinge wie „CachingPatientManager“ oder „LDAPPatientManager“ schreiben, die Anwendungsfälle könnten unzählige sein.

Der Vorteil besteht darin, dass die Programmierung der Schnittstelle in hohem Maße wiederverwendbar und testbar wird.

1137400cookie-checkinterface als Methodenparameter in Java

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy