Разница между статическими методами и методами по умолчанию в интерфейсе

107

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

public interface interfacesample2 {
    public static void method() {
        System.out.println("hello world");
    }

    public default void menthod3() {
        System.out.println("default print");
    }
}

Пожалуйста, объясните разницу между ними, а также, если есть пример, когда мы будем использовать это, было бы неплохо. Немного запутался в интерфейсах.

Випин Менон
источник
4
Вы пробовали прочитать статические методы в руководстве по Java?
Давуд ибн Карим
1
Значит, вы пропустили часть о невозможности переопределить статический метод?
Давуд ибн Карим
1
не понимал того же по интерфейсам
Випин Менон
9
статический метод является статическим членом интерфейса, не может быть переопределен (как с классом), метод по умолчанию - default implementationэто метод, который может быть переопределен.
Shail016 08
2
Просто интересно: почему ты никогда не принимал здесь ответа?
GhostCat

Ответы:

116

Различия между статическими методами и методами по умолчанию в Java 8:

1) Методы по умолчанию могут быть переопределены при реализации класса, а статические - нет .

2) Статический метод принадлежит только классу интерфейса, поэтому вы можете вызывать только статический метод в классе интерфейса, а не в классе, реализующем этот интерфейс, см.:

public interface MyInterface {
    default void defaultMethod(){
        System.out.println("Default");
    }

    static void staticMethod(){
        System.out.println("Static");
    }    
}

public class MyClass implements MyInterface {

    public static void main(String[] args) {

        MyClass.staticMethod(); //not valid - static method may be invoked on containing interface class only
        MyInterface.staticMethod(); //valid
    }
}

3) И класс, и интерфейс могут иметь статические методы с одинаковыми именами, и ни один из них не переопределяет другие!

public class MyClass implements MyInterface {

    public static void main(String[] args) {

        //both are valid and have different behaviour
        MyClass.staticMethod();
        MyInterface.staticMethod();
    }

    static void staticMethod(){
        System.out.println("another static..");
    }
}
жало
источник
2
но почему «статический»? какой цели он служит в Java 8?
Шашанк Вивек
4
Назначение ключевого слова static не изменилось - для определения членов уровня класса: полей, методов и т. Д. В Java 8 это поведение было расширено до интерфейсов, поэтому они стали более похожими на классы и теперь могут заменять класс в большинстве сценариев.
stinger
да, но мы все еще можем скрыть статический метод интерфейса вместо переопределения .... я просто думаю, что оба они выполняют одно и то же purpose( используйте общую реализацию ) и разрешают неоднозначность implementing the logic again in subclass ( переопределение, скрытие ). единственная разумная причина может быть связана с тем, что [методы статического интерфейса не наследуются] ( stackoverflow.com/questions/25169175/… ) и, следовательно, мы не можем вызывать их, используя экземпляр подкласса.
амарнатх хариш 07
29

Статический метод - это метод, который, так сказать, применяется к «пространству имен» класса. Таким образом, доступ к staticметоду fooинтерфейса Interfaceосуществляется через Interface.foo(). Обратите внимание, что вызов функции не применяется к какому-либо конкретному экземпляру интерфейса.

С barдругой стороны, реализация по умолчанию вызывается

Interface x = new ConcreteClass();
x.bar();

staticМетод интерфейса не может знать о thisпеременной, но реализация по умолчанию может.

EyasSH
источник
19

1. объясните разницу между двумя

Статические методы интерфейса похожи на методы статического класса (здесь они относятся только к интерфейсу). Если методы интерфейса по умолчанию предоставляют методы default implementationинтерфейса (которые могут реализовывать классы override).
Но помните, что если класс является implementing more than one interface with same defaultсигнатурой метода, то класс реализацииneeds to override the default method

Ниже вы можете найти простой пример (можно DIY для разных случаев)

public class Test {
    public static void main(String[] args) {
        // Accessing the static member
        I1.hello();

        // Anonymous class Not overriding the default method
        I1 t = new I1() {
            @Override
            public void test() {
                System.out.println("Anonymous test");
            }
        };
        t.test();
        t.hello("uvw");

        // Referring to class instance with overridden default method
        I1 t1 = new Test2();
        t1.test();
        t1.hello("xyz");

    }
}

interface I1 {

    void test();
    //static method
    static void hello() {
        System.out.println("hello from Interface I1");
    }

    // default need not to be implemented by implementing class
    default void hello(String name) {
        System.out.println("Hello " + name);
    }
}

class Test2 implements I1 {
    @Override
    public void test() {
        System.out.println("testing 1234...");
    }

    @Override
    public void hello(String name) {
        System.out.println("bonjour" + name);
    }
}

2. Было бы неплохо, если бы мы использовали это.

Это зависит от постановки вашей проблемы. Я бы сказал, что методы по умолчанию полезны, если вам нужна такая же реализация для метода в вашей спецификации во всех классах в этом контракте, или он может использоваться как Adapterклассы.

вот хорошее чтение: /software/233053/why-were-default-and-static-methods-added-to-interfaces-in-java-8-when-we-alread

также ниже документ оракула объясняет стандартные и статические методы для развития существующих интерфейсов:

Пользователи, у которых есть классы, реализующие интерфейсы, улучшенные новыми методами по умолчанию или статическими методами, не должны изменять или перекомпилировать их для размещения дополнительных методов.

http://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html

Shail016
источник
Я сомневаюсь. Можно ли создать объект интерфейса? В вашем коде есть такая строка: I1 t = new I1 ()
Hackinet
@Hackinet любезно прочитайте комментарий java к этому заявлению. Также читайте об анонимных классах. Надеюсь, это вам поможет.
Shail016
12

Вот мой взгляд:

статический метод в интерфейсе:

  • Вы можете вызвать его напрямую (InterfacetA.staticMethod ())

  • Подкласс не сможет переопределить.

  • Подкласс может иметь метод с тем же именем, что и staticMethod

метод по умолчанию в интерфейсе:

  • Вы не можете назвать это напрямую.

  • Подкласс сможет отменить это

Преимущество:

  • статический метод: вам не нужно создавать отдельный класс для служебного метода.

  • Метод по умолчанию: Обеспечивает общие функции в методе по умолчанию.

Виджай
источник
8

Эта ссылка содержит некоторые полезные сведения, некоторые из них перечислены здесь.

стандартные и статические методы сократили различия между интерфейсами и абстрактными классами.

Методы интерфейса по умолчанию :

  • Это помогает избежать использования служебных классов, например, все методы класса Collections могут быть предоставлены в самих интерфейсах.
  • Это помогает в расширении интерфейсов, не боясь сломать классы реализации.

Статические методы интерфейса :

  • Они являются частью интерфейса, мы не можем использовать его для объектов класса реализации.
  • Это помогает в обеспечении безопасности, не позволяя классам реализации переопределять их.

Хотел бы процитировать еще одну полезную ссылку .

Абхиджит
источник
3

Методы интерфейса по умолчанию:

Это помогает избежать использования служебных классов, например, все методы класса Collections могут быть предоставлены в самих интерфейсах.

Это помогает в расширении интерфейсов, не боясь сломать классы реализации.

Статические методы интерфейса:

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

Это помогает в обеспечении безопасности, не позволяя классам реализации переопределять их.

Теперь о статическом методе обеспечения безопасности. Посмотрим на пример.

interface MyInterface {
    /*
     * This is a default method so we need not to implement this method in the implementation classes
     */
    default void newMethod() {
        System.out.println("Newly added default method in Interface");
    }

    /*
     * This is a static method. Static method in interface is similar to default method except that we cannot override them in the implementation classes. Similar to default methods, we need to implement these methods in implementation classes so we can safely add them to the existing interfaces.
     */
    static void anotherNewMethod() {
        System.out.println("Newly added static method in Interface");
    }

    /*
     * Already existing public and abstract method We must need to implement this method in implementation classes.
     */
    void existingMethod(String str);
}

public class Example implements MyInterface {
    // implementing abstract method
    public void existingMethod(String str) {
        System.out.println("String is: " + str);
    }

    public void newMethod() {
        System.out.println("Newly added default method in Class");
    }

    static void anotherNewMethod() {
        System.out.println("Newly added static method in Class");
    }

    public static void main(String[] args) {
        Example obj = new Example();

        // calling the default method of class
        obj.newMethod();
        // calling the static method of class

        obj.anotherNewMethod();

        // calling the static method of interface
        MyInterface.anotherNewMethod();

        // calling the abstract method of interface
        obj.existingMethod("Java 8 is easy to learn");

    }
}

Здесь obj.newMethod();печать логики реализации класса означает, что мы можем изменить логику этого метода внутри класса реализации.

Но obj.anotherNewMethod();печать логики реализации класса, а не измененная реализация интерфейса. Поэтому, если какая-либо логика шифрования-дешифрования написана внутри этого метода, вы не можете изменить ее.

Сатиш Кешри
источник
этот ответ кажется, что он шел куда-то хорошо, а потом вдруг бум! нет значимого объяснения в конце. но не измененная реализация интерфейса, что это значит?
амарнатх хариш 07
2

Согласно Oracle Javadocs: http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

Методы по умолчанию позволяют добавлять новые функции к интерфейсам ваших библиотек и обеспечивать двоичную совместимость с кодом, написанным для более старых версий этих интерфейсов.

Статический метод - это метод, связанный с классом, в котором он определен, а не с каким-либо объектом. Каждый экземпляр класса использует свои статические методы.

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

Пример:

interface IDemo {

    //this method can be called directly from anywhere this interface is visible
    static int convertStrToInt(String numStr) {
       return Integer.parseInt(numStr);
    }


    //getNum will be implemented in a class
    int getNum();       

    default String numAsStr() {
       //this.getNum will call the class's implementation
       return Integer.toString(this.getNum());
    }   

}
KennyC
источник
1

Согласно документу Java14 JLS:

Метод по умолчанию:

  • Это метод экземпляра, объявленный в интерфейсе с модификатором по умолчанию.

  • Доступ к нему может получить только экземпляр реализующего класса.

  • Его тело всегда представлено блоком, который обеспечивает реализацию или поведение по умолчанию для любого реализующего класса без переопределения метода.

  • Это никогда не может быть статичным или приватным

Статический метод:

  • Его можно вызывать через интерфейс без ссылки на конкретный объект, как и статические методы класса.

  • Статический метод может быть приватным

  • Реализующий класс не может получить доступ к статическому методу

Давайте разберемся с этим с помощью приведенного ниже примера кода:

            public interface MyInterface {
        
            private void privateMethod() {
                System.out.println("Hi, this is privateMethod");
            }
        
            private static void staticPrivateMethod() {
                System.out.println("Hi, this is staticPrivateMethod");
            }
        
            static void staticMethod() {
                //privateMethod();    // Non-static method cannot be referenced from a static contex
                System.out.println("Hi, this is staticMethod");
                staticPrivateMethod();
            }
        
            default void defaultMethod() {
                System.out.println("Hi, this is defaultMethod");
            }
        
        }
    
    public class MyInterfaceImpl implements MyInterface{
        public static void main(String[] args) {
    
            MyInterface.staticMethod();
            // myInterface.staticMethod(); // Not allowed
    
            MyInterface myInterface = new MyInterfaceImpl();
            myInterface.defaultMethod();
            // MyInterface.defaultMethod(); // Not allowed
    
        }
    }
CodeAdocate
источник
0

мы не можем выполнить, Interfacesample2.menthod3();потому что это не статический метод. Для выполнения method3()нам нужен экземпляр Interfacesample2интерфейса.

Пожалуйста, найдите следующий практический пример:

public class Java8Tester {
   public static void main(String args[]){
      // Interfacesample2.menthod3(); Cannot make a static reference to the non-static method menthod3 from the type Interfacesample2

      new Interfacesample2(){ }.menthod3();// so in order to call default method we need an instance of interface

       Interfacesample2.method(); // it
   }
}

interface Interfacesample2 {
    public static void method() {
        System.out.println("hello world");
    }

    public default void menthod3() {
        System.out.println("default print");
    }
}
Премрадж
источник
0

Запуск интерфейса Java 8 также может иметь статический метод. Как и статический метод класса, статический метод интерфейса может быть вызван с использованием имени интерфейса.

пример

public interface Calculator {
    int add(int a, int b);
    int subtract(int a, int b);

    default int multiply(int a, int b) {
         throw new RuntimeException("Operation not supported. Upgrade to UltimateCalculator");
    }

    static void display(String value) {
        System.out.println(value);
    }
}

Разница между статическим методом интерфейса и методом по умолчанию заключается в том, что метод по умолчанию поддерживает наследование, а статический метод - нет. Метод по умолчанию можно переопределить при наследовании интерфейса.

Здесь можно прочитать о методе интерфейса по умолчанию и статическом методе. Метод интерфейса по умолчанию в Java 8

Ракеш Праджапати
источник
0

Все хорошие ответы здесь. Я хотел бы добавить еще одно практическое использование статической функции в интерфейсе. Совет взят из книги Джошуа Блоха «Эффективная Java, 3-е издание» в главе 2: Создание и уничтожение объекта.

Static functions can be used for static factory methods. 

Статический фабричный метод - это методы, возвращающие объект. Они работают как конструктор. В определенных случаях статический фабричный метод предоставляет более читаемый код, чем использование конструктора.

Цитата из книги - Эффективная Java, 3-е издание, Джошуа Блох

До Java 8 интерфейсы не могли иметь статических методов. По соглашению статические фабричные методы для интерфейса с именем Type были помещены в несуществующий сопутствующий класс (элемент 4) с именем Types.

Автор приводит пример Коллекций, в которых реализован такой статический фабричный метод. Проверяя код, можно увидеть Джоша Блоха как первого автора класса Collections. Хотя Коллекции - это класс, а не интерфейс. Но концепция все еще актуальна.

Например, Java Collections Framework имеет сорок пять служебных реализаций своих интерфейсов, обеспечивающих неизменяемые коллекции, синхронизированные коллекции и т.п. Почти все эти реализации экспортируются через статические фабричные методы в один неинстанцируемый класс (java.util.Collections). Все классы возвращаемых объектов не являются общедоступными.

Далее он объясняет, что API не только меньше, он помогает с читабельностью кода и легкостью API.

Уменьшается не только основная часть API, но и концептуальный вес: количество и сложность концепций, которые программисты должны освоить, чтобы использовать API. Программист знает, что возвращаемый объект имеет именно тот API, который указан в его интерфейсе, поэтому нет необходимости читать дополнительную документацию по классу для класса реализации.

Вот один из статических методов из класса java.util.Collections:

public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
    return new UnmodifiableCollection<>(c);
}
Джей Раджпут
источник