Может ли метод интерфейса иметь тело?
Я знаю, что интерфейс похож на 100% чистый абстрактный класс. Таким образом, в нем не может быть реализации метода. Но я увидел странный код. Кто-нибудь может это объяснить?
Фрагмент кода:
interface Whoa {
public static void doStuff() {
System.out.println("This is not default implementation");
}
}
РЕДАКТИРОВАТЬ:
Моя IDE - это Intellij Idea 13.1. SDK проекта - это Java 7 <1.7.0_25>. В среде IDE не отображается ошибка компилятора. Но, когда я компилирую код в командной строке, я получаю следующее сообщение.
Whoa.java:2: error: modifier static not allowed here public static void doStuff() { ^
4 ответа
В Java 8 вы можете определять статические методы в интерфейсах в дополнение к методам по умолчанию.
Статический метод - это метод, связанный с классом, в котором он определен, а не с каким-либо объектом. Каждый экземпляр класса разделяет свои статические методы.
Это облегчает вам организацию вспомогательных методов в ваших библиотеках; вы можете хранить статические методы, специфичные для интерфейса, в том же интерфейсе, а не в отдельном классе.
В следующем примере определяется статический метод, который извлекает
ZoneId
объект, соответствующий идентификатору часового пояса; он использует часовой пояс системы по умолчанию, если нетZoneId
объект, соответствующий заданному идентификатору. (В результате вы можете упростить методgetZonedDateTime
)
Вот код:
public interface TimeClient {
// ...
static public ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
default public ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}
Смотрите также
Для всего интересного в Java 8 прочитайте Все о Java 8
Это возможно только в Java 8. В спецификации языка Java 7 §9.4 в ней прямо говорится:
Это ошибка времени компиляции, если метод, объявленный в интерфейсе, объявлен как статический, потому что статические методы не могут быть абстрактными.
Поэтому в Java 7 статические методы в интерфейсах не могут существовать.
Если вы перейдете к спецификации языка Java 8 §9.4.3, вы увидите, что она говорит:
Статический метод также имеет тело блока, которое обеспечивает реализацию метода.
Так что прямо говорится, что в Java 8 они могут существовать.
Я даже пытался запустить ваш точный код в Java 1.7.0_45, но он выдал ошибку "модификатор static не разрешен здесь".
Вот цитата непосредственно из учебника по Java 8, Методы по умолчанию (Изучение языка Java> Интерфейсы и наследование):
Статические Методы
В дополнение к методам по умолчанию вы можете определять статические методы в интерфейсах. (Статический метод - это метод, связанный с классом, в котором он определен, а не с каким-либо объектом. Каждый экземпляр класса совместно использует свои статические методы.) Это упрощает организацию вспомогательных методов в ваших библиотеках; вы можете хранить статические методы, специфичные для интерфейса, в том же интерфейсе, а не в отдельном классе. В следующем примере определяется статический метод, который извлекает
ZoneId
объект, соответствующий идентификатору часового пояса; он использует часовой пояс системы по умолчанию, если нетZoneId
объект, соответствующий заданному идентификатору. (В результате вы можете упростить методgetZonedDateTime
):public interface TimeClient { // ... static public ZoneId getZoneId (String zoneString) { try { return ZoneId.of(zoneString); } catch (DateTimeException e) { System.err.println("Invalid time zone: " + zoneString + "; using default time zone instead."); return ZoneId.systemDefault(); } } default public ZonedDateTime getZonedDateTime(String zoneString) { return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString)); } }
Как и статические методы в классах, вы указываете, что определение метода в интерфейсе является статическим методом с
static
ключевое слово в начале подписи метода. Все объявления методов в интерфейсе, включая статические, неявноpublic
, так что вы можете опуститьpublic
модификатор.
Для Java версии 7 или ниже, аналогично функционально вы можете добиться, используя вложенный класс, объявленный в теле интерфейса. и этот вложенный класс реализует внешний интерфейс.
Пример:
interface I1{
public void doSmth();
class DefaultRealizationClass implements I1{
@Override
public void doSmth() {
System.out.println("default realization");
}
}
}
Как мы используем это в нашем коде?
class MyClass implements I1{
@Override
public void doSmth() {
new I1.DefaultRealizationClass().doSmth();
}
}
Поэтому реализация по умолчанию заключена в интерфейсе.
За этот период интерфейсы Java сильно развились, и Java 8 полностью изменила представление об интерфейсах.
Что касается вопроса, да, мы можем иметь тело метода в интерфейсе.
тогда как в java 8 у нас может быть тело метода в статическом методе и в методе по умолчанию, как в приведенном ниже примере.
interface CheckMyEvolution{
default void whatsNew() {
System.out.print("Hello there!Check my Evolution");
}
static ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +
"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
}
у нас также может быть частный метод в интерфейсах, начиная с java 9. как показано ниже, код хорошо компилируется в версиях java 9 и выше, но не работает в версиях java 8 и ниже.
interface CheckMyEvolution{
default void whatsNew() {
checkIt();
}
// Private method
private void checkIt() {
System.out.println("Hello there! I can have private method now. Make sure you are using JDK 9 or Above.");
}
}
public class CheckMyEvolutionImpl implements CheckMyEvolution{
public static void main(String[] args) {
CheckMyEvolution evolution= new CheckMyEvolutionImpl();
evolution.whatsNew();
}
}
Ссылки: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html[https://www.quora.com/profile/Rajat-Singh-187/Private-Method-in-the-Java-интерфейс]