Verschachtelung mit Java-Schnittstellen

Wenn Sie mein Java 101- Lernprogramm gelesen haben, in dem statische und innere Klassen vorgestellt werden, sollten Sie mit den Grundlagen der Arbeit mit verschachtelten Klassen in Java-Code vertraut sein. In diesem Java-Tipp lernen Sie drei gängige Methoden zur Verwendung von Verschachtelungstechniken mit Java-Schnittstellen kennen. Ich werde auch kurz Verschachtelungsschnittstellen mit statischen Methoden demonstrieren, die auch als statische Methodenschnittstellen bezeichnet werden.

Weitere Informationen zu Java-Schnittstellen

Eine Einführung in Java-Schnittstellen, einschließlich des Unterschieds zwischen Klassen und Schnittstellen, finden Sie in meinem Java 101- Lernprogramm Arbeiten mit Schnittstellen in Java.

Verschachtelungsschnittstellen in Klassen

Mit Java können Sie Schnittstellen innerhalb von Klassen deklarieren. Einmal deklariert, ist eine Schnittstelle automatisch ein statisches Mitglied der Klasse. Es ist nicht erforderlich, die Schnittstelle mit dem staticSchlüsselwort zu deklarieren . Betrachten Sie das folgende Beispiel:

 class EnclosingClass { interface EnclosedInterface1 { } static interface EnclosedInterface2 { } } 

EnclosedInterface1und EnclosedInterface2sind statische Elementschnittstellen . Es gibt keine Entsprechung zu lokalen Klassen, da Schnittstellen nicht in Blöcken deklariert werden können. Schnittstellen können jedoch in anonymen Klassenkontexten verwendet werden.

Auf verschachtelte Schnittstellen wird normalerweise nicht von außerhalb ihrer umschließenden Klassen zugegriffen. Andernfalls können Sie sie als Schnittstellen der obersten Ebene deklarieren . Stattdessen wird von innerhalb ihrer umschließenden Klassen auf sie zugegriffen, wie hier gezeigt:

 class EnclosingClass { interface EnclosedInterface1 { } static interface EnclosedInterface2 { } static class EnclosedClass1 implements EnclosedInterface1, EnclosedInterface2 { } class EnclosedClass2 implements EnclosedInterface1, EnclosedInterface2 { } void m() { class EnclosedClass3 implements EnclosedInterface1, EnclosedInterface2 { } new EnclosedInterface1() { }; } } 

Beachten Sie, dass die statische Elementklasse EnclosedClass1, die nicht statische Elementklasse EnclosedClass2und die lokale Klasse EnclosedClass3beide verschachtelten Schnittstellen implementieren. In einem anonymen Klassenkontext kann jedoch nur eine Schnittstelle implementiert werden. (Weitere Informationen zu anonymen Klassen finden Sie unter Statische Klassen und innere Klassen in Java.)

Klassen mit verschachtelten Schnittstellen in java.net

Die Standardklassenbibliothek von Java enthält Klassen mit verschachtelten Schnittstellen. Beispielsweise deklariert InetAddress(im java.netPaket), das eine Internetprotokolladresse darstellt, eine private AddressesSchnittstelle, die von privaten CachedAddressesund NameServiceAddressesstatischen Mitgliedsklassen implementiert wird . Außerdem wird eine private NameServiceSchnittstelle deklariert , die von privaten PlatformNameServiceund HostsFileNameServicestatischen Elementklassen implementiert wird .

Verschachteln von Schnittstellen in Schnittstellen

Mit Java können Sie auch Schnittstellen innerhalb von Schnittstellen deklarieren. In diesem Fall ist eine verschachtelte Schnittstelle ein statisches Mitglied ihrer umschließenden Schnittstelle, und das staticSchlüsselwort ist wiederum redundant. Außerdem ist die verschachtelte Schnittstelle implizit öffentlich. Hier ist ein Beispiel:

 interface EnclosingInterface { interface EnclosedInterface1 // implicitly static and public { } static interface EnclosedInterface2 // explicitly static and implicitly public { } } 

Sie greifen auf eine geschlossene Schnittstelle zu, indem Sie ihrem Namen den Namen der umschließenden Schnittstelle und den Operator für den Mitgliederzugriff voranstellen. Geben Sie beispielsweise EnclosingInterface.EnclosedInterface1den Zugriff an EnclosedInterface1.

Verschachtelte Schnittstellen im Java Collections Framework

Das Java Collections Framework bietet Einblicke in die Nützlichkeit der Verschachtelung einer Schnittstelle in einer anderen. Betrachten Sie die java.util.MapSchnittstelle, die eine Karte beschreibt (eine Sammlung von Schlüssel-Wert-Paaren). Die MapSchnittstelle abstrahiert, was es bedeutet, eine Karte zu sein. Klassen wie HashMapund java.util.TreeMapimplementieren Map, die verschiedene Arten von Kartenimplementierungen beschreiben.

Maperklärt Entryals eines seiner Mitglieder. Entryist eine verschachtelte Schnittstelle, die ein Schlüssel-Wert-Paar beschreibt. Die EntrySchnittstelle wird Mapaufgrund der engen Beziehung zwischen den beiden Schnittstellen deklariert - jeder Eintrag muss zu einer Karte gehören. Entrywird von den java.util.AbstractMapKlassen der Klasse SimpleEntryund der SimpleImmutableEntrystatischen Mitglieder implementiert . Normalerweise ignorieren Sie diese statischen Elementklassen und interagieren Map.Entrystattdessen mit.

Verschachteln von Klassen in Schnittstellen

Eine der merkwürdigsten Sprachfunktionen von Java ist die Möglichkeit, eine Klasse in einer Schnittstelle zu verschachteln. Wie bei einer verschachtelten Schnittstelle ist die verschachtelte Klasse implizit öffentlich und statisch. Hier ist ein Beispiel:

 interface EnclosingInterface { class EnclosedClass { } } 

Trotz seiner Seltsamkeit kann es nützlich sein, eine Klasse in einer Schnittstelle zu verschachteln, insbesondere wenn eine enge Beziehung zwischen der einschließenden Schnittstelle und der eingeschlossenen Klasse besteht. Das Erfassen dieser Beziehung verbessert die Lesbarkeit des Quellcodes. In Fällen, in denen Klasse und Schnittstelle denselben Namen tragen, können Sie durch Verschachtelung auch einen Namenskonflikt zwischen beiden vermeiden.

Beispiel: Die adressierbare Schnittstelle enthält die Adressklasse

Angenommen, Sie möchten adressierbare Entitäten wie Briefe, Postkarten und Pakete modellieren. Jede Entität wird durch ihre eigene Klasse beschrieben, aber alle haben die Gemeinsamkeit, an ein bestimmtes Ziel adressierbar zu sein. Jede Klasse kann mit doppelten Adressfeldern entworfen werden, oder Sie können diese Details in eine gemeinsame Oberklasse abstrahieren. Alternativ können Sie die AddressableBenutzeroberfläche von Listing 1 nutzen .

Listing 1. Addressable.java

 public interface Addressable { public class Address { private String boxNumber; private String street; private String city; public Address(String boxNumber, String street, String city) { this.boxNumber = boxNumber; this.street = street; this.city = city; } public String getBoxNumber() { return boxNumber; } public String getStreet() { return street; } public String getCity() { return city; } public String toString() { return boxNumber + " - " + street + " - " + city; } } public Address getAddress(); } 

Die AddressableSchnittstelle beschreibt eine adressierbare Entität als eine Adresse enthaltend. Diese Adresse wird von der verschachtelten AddressKlasse beschrieben. Die getAddress()Methode wird von jeder Klasse implementiert, die implementiert wird Addressable.

Listing 2 zeigt den Quellcode einer LetterKlasse, die implementiert Addressable.

Listing 2. Letter.java

 public class Letter implements Addressable { private Addressable.Address address; public Letter(String boxNumber, String street, String city) { address = new Addressable.Address(boxNumber, street, city); } public Address getAddress() { return address; } } 

Letterspeichert ein einzelnes addressFeld vom Typ Addressable.Address. Diese verschachtelte Klasse wird vom LetterKonstruktor instanziiert . Die implementierte getAddress()Methode gibt dieses Objekt zurück.

Überlegen Sie nun, was passiert, wenn wir der Anwendung Klassen hinzufügen Postcardund ParcelKlassen hinzufügen Addressables. Listing 3 zeigt die Quellcode einer AddressablesAnwendung, die die zeigt Postcard, Parcelund LetterTypen.

Listing 3. Addressables.java

 public class Addressables { public static void main(String[] args) { Addressable[] addressables = { new Letter("100", "Main Street", "Town A"), new Postcard("200", "Waterfront Drive", "Town B"), new Parcel("300", "10th Ave", "Town C") }; for (int i = 0; i < addressables.length; i++) System.out.println(addressables[i].getAddress()); } }

The main() method first creates an array of Addressable objects. It then iterates over these objects, invoking getAddress() on each object. The returned Addressable.Address object's toString() method is invoked by System.out.println() to return a string representation of the object, and this representation is subsequently output.

Compile Listings 2 and 3 along with Postcard.java and Parcel.java as follows:

 javac *.java 

Run the application as follows:

 java Addressables 

You should observe the following output:

 100 - Main Street - Town A 200 - Waterfront Drive - Town B 300 - 10th Ave - Town C 

Nested interfaces with static methods (static method interfaces)

Many developers believe that nesting a class in an interface violates object-oriented programming and the purpose for an interface. However, it's good to know about this capability because you might encounter it when maintaining someone else's code. Furthermore, now that interfaces have evolved to include default and static methods, you might encounter additional reasons to nest a class in an interface. As an example, here is a local class nested within a static method interface:

 interface I { static void m() { class C { } } } 

Conclusion

I've presented three common ways to use nesting techniques with Java classes and interfaces, and also demonstrated a controversial technique of nesting interfaces with static methods. See the complete Java 101 tutorial to learn more about nesting with static classes and inner classes in Java.

Diese Geschichte "Verschachteln mit Java-Schnittstellen" wurde ursprünglich von JavaWorld veröffentlicht.