Різниця між статичними та типовими методами в інтерфейсі


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
не розумів того ж на інтерфейсах
Vipin Menon

9
статичний метод є статичним членом Інтерфейсу, його не можна перекрити (як у класі), типовим методом є default implementationметод, який може бути замінений.
Shail016

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
Призначення статичного ключового слова не змінюється - визначати членів рівня класу: поля, методи тощо. У Java 8 така поведінка була розширена на інтерфейси, тому вони стають більш схожими на класи та тепер можуть замінити клас у більшості сценаріїв.
stinger

Так, але ми все ще можемо приховати статичний метод інтерфейсу замість переосмислення .... Я просто думаю, що обидва виконують те саме purpose( використовуємо загальну реалізацію ) і вирішує двозначність шляхом implementing the logic again in subclass ( переосмислення, приховування ). єдиною розумною причиною буде тому, що [статичні методи інтерфейсу не успадковуються] ( stackoverflow.com/questions/25169175/… ), і тому ми не можемо викликати їх за допомогою екземпляра підкласу.
amarnath Harish

29

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

З barіншого боку, реалізація за замовчуванням викликається

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

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


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

також нижче oracle doc пояснює стандартні та статичні методи для розвитку існуючих інтерфейсів:

Користувачам, у яких є класи, які реалізують інтерфейси, вдосконалені новими методами за замовчуванням або статичними методами, не потрібно їх змінювати чи перекомпілювати для розміщення додаткових методів.

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


У мене є сумніви. Чи можливо створити об’єкт інтерфейсу? У вашому коді є такий рядок: I1 t = новий 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();логіка реалізації класу друку, але не змінена реалізація інтерфейсу. Отже, якщо будь-яку логіку шифрування-дешифрування, записану всередині цього методу, ви не можете змінити.


ця відповідь здається, що це було кудись добре, то раптом бум! ніякого змістовного пояснення в кінці. але не змінена реалізація інтерфейсу, що це означає?
amarnath Harish

2

Відповідно до Javadocs Oracle: http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

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

Статичний метод - це метод, який асоціюється з класом, у якому він визначений, а не з будь-яким об'єктом. Кожен екземпляр класу ділиться своїми статичними методами.

Зазвичай статичний метод в інтерфейсі використовується як Helper методи, тоді як метод за замовчуванням використовується як реалізація за замовчуванням для класів, які реалізують цей інтерфейс.

Приклад:

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

}

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
    
        }
    }

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.

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

Наприклад, 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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.