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

Я знаю, что интерфейс похож на 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 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-интерфейс]

Другие вопросы по тегам