Ако сте прочели моя урок за Java 101, представящ статични класове и вътрешни класове, трябва да сте запознати с основите на работата с вложени класове в Java кода. В този съвет на Java ще научите три често срещани начина за използване на техники за влагане с Java интерфейси. Също така ще демонстрирам накратко интерфейси за влагане със статични методи, известни също като интерфейси за статични методи.
Повече за Java интерфейсите
За въведение в интерфейсите на Java, включително разликата между класове и интерфейси, вижте моя урок за Java 101 Работа с интерфейси в Java.
Влагане на интерфейси в класове
Java ви позволява да декларирате интерфейси вътре в класовете. Веднъж деклариран, интерфейсът автоматично е статичен член на класа. Не е необходимо да декларирате интерфейса с static
ключовата дума. Обмислете следния пример:
class EnclosingClass { interface EnclosedInterface1 { } static interface EnclosedInterface2 { } }
EnclosedInterface1
и EnclosedInterface2
са статични интерфейси на членове . Няма еквивалент на локални класове, защото интерфейсите не могат да бъдат декларирани в блокове. Интерфейсите обаче могат да се използват в контексти на анонимни класове.
Вложените интерфейси обикновено не са достъпни отвъд заграждащите ги класове. В противен случай можете да ги декларирате като интерфейси от най-високо ниво . Вместо това те са достъпни от вътрешните им класове, както е показано тук:
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() { }; } }
Обърнете внимание, че статичният клас член EnclosedClass1
, нестатичният член член EnclosedClass2
и локалният клас EnclosedClass3
изпълняват и двата вложени интерфейса. Въпреки това, само един интерфейс може да бъде реализиран в контекст на анонимен клас. (Вижте статични класове и вътрешни класове в Java за повече информация относно анонимните класове.)
Класове с вложени интерфейси в java.net
Стандартната библиотека на класове на Java включва класове с вложени интерфейси. Например InetAddress
(в java.net
пакета), който представлява адрес на интернет протокол, декларира частен Addresses
интерфейс, който е реализиран от частни CachedAddresses
и NameServiceAddresses
статични класове членове. Той също така декларира частен NameService
интерфейс, който е реализиран от частни PlatformNameService
и HostsFileNameService
статични класове членове.
Влагане на интерфейси в интерфейси
Java също ви позволява да декларирате интерфейси вътре в интерфейсите. В този случай вложен интерфейс е статичен член на заграждащия го интерфейс и отново static
ключовата дума е излишна. Също така, вложеният интерфейс е имплицитно публичен. Ето пример:
interface EnclosingInterface { interface EnclosedInterface1 // implicitly static and public { } static interface EnclosedInterface2 // explicitly static and implicitly public { } }
Имате достъп до затворен интерфейс, като добавяте името му пред името на заграждащия интерфейс и оператора за достъп на членове. Например посочете EnclosingInterface.EnclosedInterface1
за достъп EnclosedInterface1
.
Вложени интерфейси в Java Collections Framework
Рамката на Java Collections дава представа за полезността на влагането на един интерфейс в друг. Помислете за java.util.Map
интерфейса, който описва карта (колекция от двойки ключ-стойност). В Map
интерфейса резюмета какво означава да си на карта. Класове като HashMap
и java.util.TreeMap
изпълнение Map
, описващи различни видове внедряване на карти.
Map
декларира Entry
като един от своите членове. Entry
е вложен интерфейс, който описва двойка ключ-стойност. В Entry
интерфейса е обявен в Map
поради тясната връзка между двата интерфейса - всеки запис трябва да принадлежи на картата. Entry
се реализира от java.util.AbstractMap
класовете SimpleEntry
и SimpleImmutableEntry
статичните членове на класа. Обикновено ще игнорирате тези статични класове членове и ще взаимодействате с тях Map.Entry
.
Класове за влагане в интерфейси
Една от по-непознатите езикови характеристики на Java е възможността за влагане на клас в интерфейс. Както при вложения интерфейс, вложеният клас е имплицитно публичен и статичен. Ето пример:
interface EnclosingInterface { class EnclosedClass { } }
Въпреки неговата странност, възможността за влагане на клас в интерфейса може да бъде полезна, особено когато има тясна връзка между заграждащия интерфейс и затворения клас. Заснемането на тази връзка подобрява четливостта на изходния код. В случаите, когато класът и интерфейсът носят едно и също име, влагането също може да ви помогне да избегнете конфликт на имена между двете.
Пример: Адресируемият интерфейс затваря адресния клас
Да предположим, че искате да моделирате адресируеми обекти като писма, пощенски картички и колети. Всеки обект ще бъде описан от свой собствен клас, но всички те споделят общото, че могат да бъдат адресирани до някаква дестинация. Всеки клас може да бъде проектиран с дублирани полета за адрес или може да абстрахирате тези подробности в общ суперклас. Като алтернатива можете да използвате Addressable
интерфейса на Листинг 1 .
Листинг 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(); }
В Addressable
интерфейса описва адресируема единица като съдържаща адрес. Този адрес е описан от вложения Address
клас. В getAddress()
метода се осъществява от каквото и клас изпълнява Addressable
.
Листинг 2 представя изходния код на Letter
клас, който изпълнява Addressable
.
Листинг 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; } }
Letter
съхранява едно address
поле от тип Addressable.Address
. Този вложен клас е създаден от Letter
конструктора на '. Реализираният getAddress()
метод връща този обект.
Сега помислете какво се случва, когато добавяме Postcard
и Parcel
класове към Addressables
приложението. Обява 3 съдържа изходния код на Addressables
приложение, което показва Postcard
, Parcel
и Letter
видовете.
Листинг 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.
Тази история „Влагане с Java интерфейси“ първоначално е публикувана от JavaWorld.