Необходимо обязательно следить за доступами! У interface доступы к методам всегда public, а в классе, реализующем может быть не указан модификатор доступа, который по умолчанию = default package-private. Это приведет к ошибке:
1 2 3 4 5 6 7
publicinterfaceX { voiddo(); }
publicclassYimplementsX { voiddo() { } // ошибка в связи с понижением доступа с public на package-private }
classZimplementsX, Y {...} // ошибка, т.к. методы do имеют несовместимые типы
interfaceY2 { Number do(); }
classZimplementsX, Y2 {} // ошибка, см. выше
interfaceX2 { Integer do(); }
classImplOkimplementsX2, Y2 { public Integer do() {} }
Класс ImplOk определен корректно, т.к. Integer наследуется от Number, а как отмечалось ранее, на уточнение класса при возврате из метода, компилятор реагирует без ошибок.
Type-cast
Как отмечалось ранее, type-cast класса в может быть с ошибкой компиляции, если классы никак не связаны между собой (это касается и instanceof):
1 2
Numberx=1; if(x instanceof String) // ошибка компиляции - String никак не связан с Number
Но для интерфейсов данное правило не работает:
1 2
Numberx=1; if(x instanceof List) // ок, но всегда будет false
Указанное выше правило не работает в случае классов, помеченных как final
Xx=newX(); if(x instanceof List) // допустимо, т.к. List - интерфейс if(x instanceof String) // ошибка компиляции - нет связанности if(x instanceof Integer) // ошибка компиляции - нет связанности
Yy=newY(); if(y instanceof Number) // ошибка компиляции - нет связанности
Zz=newZ(); if(z instanceof List) // ошибка компиляции. Хоть List и интерфейс, но класс объявлен как final
Interface методы
Interface default-метод
может применяться только к методам интерфейса;
должен иметь тело метода;
должен быть public;
не может быть abstract, final или static;
может быть переопределен в реализации;
если класс наследуется от 2 интерфейсов с default маркерами, то метод необходимо будет переопределять (возможно, вызов конкретной реализации в любом из интерфейсов).
Такое же правило касается и наследования одним интерфейсом других - несколько default методов необходимо свести в одну единую реализацию метода.
Interface static-метод
может не указывать модификатор доступа - тогда он будет public. Если указывать, то доступен только public;
если метод имеет static, значит должен иметь тело метода;
не может быть final или abstract;
не может быть переопределен;
при обращении может быть использовано только имя данного интерфейса (не наследников).
1 2 3
publicinterfaceX { staticvoiddo() {...} }
Interface private-метод
должен содержать тело;
может быть использован только default и private (но не private static) методами того же интерфейса:
1 2 3 4 5 6 7
publicinterfaceX { defaultvoidgo() { doGo(); }
privatevoiddoGo() { ... } }
Поскольку метод не будет виден классами, реализующими интерфейс, данные методы очень удобны когда необходимо ограничить видимость метода, но при этом, распространить его действие на все реализующие классы.
Interface private-static-метод
должен содержать тело;
могут быть вызваны любым методом, но только в рамках этого интерфейса.