На практике это может не иметь большого значения, но я хотел уточнить, что явная реализация интерфейса не является точно такой же, как реализация его с помощью наследования. Разница присутствует в скомпилированных файлах классов и видна через отражение. Например.,
for (Class<?> c : ArrayList.class.getInterfaces())
System.out.println(c);
Вывод показывает только интерфейсы явно , реализованные ArrayList
, в том порядке, в котором они были записаны в источнике, который [в моей версии Java]:
interface java.util.List
interface java.util.RandomAccess
interface java.lang.Cloneable
interface java.io.Serializable
Выходные данные не включают интерфейсы, реализованные суперклассами, или интерфейсы, которые являются суперинтерфейсами тех, которые включены. В частности, Iterable
и Collection
отсутствуют в вышеприведенном, хотя ArrayList
реализует их неявно. Чтобы найти их, вы должны рекурсивно повторить иерархию классов.
Было бы прискорбно, если какой-то код использует отражение и зависит от явной реализации интерфейсов, но это возможно, поэтому сопровождающие библиотеки коллекций могут неохотно менять ее сейчас, даже если они этого захотят. (Существует наблюдение под названием Закон Хайрама : «При достаточном количестве пользователей API не имеет значения, что вы обещаете в контракте; кто-то будет зависеть от всех наблюдаемых действий вашей системы») .)
К счастью, это различие не влияет на систему типов. Выражения new ArrayList<>() instanceof Iterable
и Iterable.class.isAssignableFrom(ArrayList.class)
по-прежнему оцениваются в true
.