Может ли метод интерфейса иметь тело?

Я знаю, что интерфейс подобен абстрактному классу с чистотой 100%. Таким образом, в нем не может быть реализации метода. Но я увидел странный код. Кто-нибудь может объяснить это?

Фрагмент кода:

 interface Whoa {
        public static void doStuff() {
            System.out.println("This is not default implementation");
        }
 }

EDIT:

Моя IDE - это идея Intellij 13.1. SDK проекта - java 7 и 1.7.0_25 > . В IDE не отображается какая-либо ошибка компилятора. Но, когда я компилирую код в командной строке, я получаю следующее сообщение.

Whoa.java:2: error: modifier static not allowed here
    public static void doStuff() {
                       ^

Ответ 1

От 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));
   }    
}

См. также

Ответ 2

Это возможно только в 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.

Ответ 3

Для 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();
    }   
}

Поэтому реализация по умолчанию инкапсулирована внутри интерфейса.

Ответ 4

Для Java версии 9 в дополнение к статическим и стандартным методам интерфейс теперь также может содержать частные методы, что может быть очень полезно:

public interface DemoInterface {    
    void ordinaryInterfaceMethod();

    default void method1() {
        print();
    }

    default void method2() {
        print();
    }

    private void print() {
        System.out.println("Hello World!");
    }    
}

Частный метод не является частью публичного API, открытого интерфейсом и может совместно использовать общие функции.