Różnica między metodami statycznymi i domyślnymi w interfejsie

107

Uczyłem się poprzez interfejsy, kiedy zauważyłem, że teraz możesz zdefiniować statyczne i domyślne metody w interfejsie.

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

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

Uprzejmie wyjaśnij różnicę między tymi dwoma, a także jeśli istnieje przykład, kiedy użylibyśmy tego, byłoby miło. Trochę zdezorientowany na interfejsach.

Vipin Menon
źródło
4
Czy próbowałeś przeczytać o metodach statycznych w samouczku Java?
Dawood ibn Kareem
1
Więc przegapiłeś część dotyczącą tego, że nigdy nie będziesz w stanie zastąpić metody statycznej?
Dawood ibn Kareem
1
nie rozumiał tego samego na interfejsach
Vipin Menon
9
Metoda statyczna jest statycznym elementem składowym interfejsu, nie można jej zastąpić (tak jak w przypadku klasy), metoda domyślna jest default implementationmetodą, która może zostać zastąpiona.
Shail016
2
Zastanawiam się tylko: dlaczego nigdy nie przyjąłeś tutaj odpowiedzi?
GhostCat

Odpowiedzi:

116

Różnice między metodami statycznymi i domyślnymi w Javie 8:

1) Metody domyślne można zastąpić w implementacji klasy, podczas gdy statyczne nie mogą .

2) Metoda statyczna należy tylko do klasy Interface, więc metodę statyczną można wywołać tylko w klasie Interface, a nie w klasie implementującej ten interfejs, zobacz:

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) Zarówno klasa, jak i interfejs mogą mieć statyczne metody o takich samych nazwach i żadna z nich nie zastępuje innych!

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..");
    }
}
żądło
źródło
2
ale dlaczego „statyczne”? czemu służy w Javie 8?
Shashank Vivek
4
Cel słowa kluczowego static nie zmienił się - aby zdefiniować składowe na poziomie klasy: pola, metody itp. W Javie 8 to zachowanie zostało rozszerzone na interfejsy, dzięki czemu stają się one bardziej podobne do klas i teraz mogą zastąpić klasę w większości scenariuszy.
stinger
tak, ale nadal możemy ukryć metodę statyczną interfejsu zamiast przesłonić, .... po prostu myślę, że zarówno spełnia to samo purpose( użyj wspólnej implementacji ), jak i rozwiązuje niejednoznaczność implementing the logic again in subclass ( przesłanianie, ukrywanie ). jedynym rozsądnym powodem byłby powód, dla którego [statyczne metody interfejsu nie są dziedziczone] ( stackoverflow.com/questions/25169175/… ) i dlatego nie możemy ich wywoływać przy użyciu instancji podklasy.
amarnath harish
29

Metoda statyczna to metoda, która odnosi się, że tak powiem, do „przestrzeni nazw” klasy. Więc astatic metoda foointerfejsu Interfacejest dostępna przez Interface.foo(). Należy zauważyć, że wywołanie funkcji nie ma zastosowania do żadnej konkretnej instancji interfejsu.

Z bardrugiej strony jest wywoływana implementacja domyślna

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

staticMetoda interfejs nie może wiedzieć o thiszmiennej, ale domyślna implementacja może.

EyasSH
źródło
19

1. wyjaśnij różnicę między tymi dwoma

Statyczne metody interfejsu są podobne do statycznych metod klasowych (tutaj należą tylko do interfejsu). Gdzie jako domyślne metody interfejsu udostępniają metody default implementationinterfejsu (które mogą implementować klasy override)
Ale pamiętaj, jeśli klasa jestimplementing more than one interface with same default sygnaturą metody, to klasa implementującaneeds to override the default method

Poniżej znajdziesz prosty przykład (można wykonać majsterkowanie w różnych przypadkach)

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. kiedy byśmy tego użyli, byłoby miło.

To zależy od twojego stwierdzenia problemu. Powiedziałbym, że metody domyślne są przydatne, jeśli potrzebujesz tej samej implementacji dla metody w swojej specyfikacji we wszystkich klasach w tym kontrakcie lub mogą być używane jak Adapterklasy.

tutaj jest dobra lektura: /software/233053/why-were-default-and-static-methods-added-to-interfaces-in-java-8-when-we-alread

również poniżej oracle doc wyjaśnia domyślne i statyczne metody rozwijania istniejących interfejsów:

Użytkownicy, którzy mają klasy, które implementują interfejsy rozszerzone o nowe metody domyślne lub statyczne, nie muszą ich modyfikować ani rekompilować w celu dostosowania do dodatkowych metod.

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

Shail016
źródło
Mam wątpliwości. Czy można stworzyć obiekt interfejsu? Twój kod ma następującą linię: I1 t = new I1 ()
Hackinet
@Hackinet uprzejmie przeczytaj komentarz Java dotyczący tego oświadczenia. Przeczytaj również o zajęciach anonimowych. Mam nadzieję, że ci to pomoże.
Shail016
12

Oto mój pogląd:

metoda statyczna w interfejsie:

  • Możesz zadzwonić bezpośrednio (InterfacetA.staticMethod ())

  • Podklasa nie będzie mogła zastąpić.

  • Podklasa może mieć metodę o tej samej nazwie co staticMethod

domyślna metoda w interfejsie:

  • Nie możesz zadzwonić bezpośrednio.

  • Podklasa będzie mogła to zmienić

Korzyść:

  • Metoda statyczna: nie musisz tworzyć osobnej klasy dla metody narzędziowej.

  • Metoda domyślna: Zapewnij typową funkcjonalność w metodzie domyślnej.

Vijay
źródło
8

Ten link zawiera przydatne spostrzeżenia, kilka z nich wymieniono tutaj.

Metody domyślne i statyczne zlikwidowały różnice między interfejsami a klasami abstrakcyjnymi .

Domyślne metody interfejsu :

  • Pomaga to w unikaniu klas narzędzi, takich jak wszystkie metody klasy Collections, które można udostępnić w samych interfejsach.
  • Pomaga w rozszerzaniu interfejsów bez obawy o zerwanie klas implementacyjnych.

Metody statyczne interfejsu :

  • Są częścią interfejsu, nie możemy ich używać do obiektów klas implementacyjnych.
  • Pomaga w zapewnieniu bezpieczeństwa, ponieważ nie pozwala klasom implementacji ich zastępować.

Chciałbym zacytować inne przydatne odniesienie .

Abhijeet
źródło
3

Domyślne metody interfejsu:

Pomaga to w unikaniu klas narzędzi, takich jak wszystkie metody klasy Collections, które można udostępnić w samych interfejsach.

Pomaga w rozszerzaniu interfejsów bez obawy o zerwanie klas implementacyjnych.

Metody statyczne interfejsu:

Są częścią interfejsu, nie możemy ich używać do obiektów klas implementacyjnych.

Pomaga w zapewnieniu bezpieczeństwa, ponieważ nie pozwala klasom implementacji ich zastępować.

Teraz jak statyczna metoda zapewniająca bezpieczeństwo. Zobaczmy przykład.

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");

    }
}

Tutaj obj.newMethod();logika implementacji klasy drukowania oznacza, że ​​możemy zmienić logikę tej metody wewnątrz klasy implementacyjnej.

Ale obj.anotherNewMethod();logika implementacji klasy drukowania, ale nie zmieniona implementacja interfejsu. Więc jeśli jakakolwiek logika szyfrowania-deszyfrowania zapisana w tej metodzie nie jest możliwa.

Satish Keshri
źródło
ta odpowiedź wydaje się, że idzie dobrze, a potem nagle bum! brak sensownego wyjaśnienia na końcu. ale nie zmieniono implementacji interfejsu, co to oznacza?
amarnath harish
2

Według Oracle Javadocs: http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

Metody domyślne umożliwiają dodawanie nowych funkcji do interfejsów bibliotek i zapewniają zgodność binarną z kodem napisanym dla starszych wersji tych interfejsów.

Metoda statyczna to metoda skojarzona z klasą, w której została zdefiniowana, a nie z jakimkolwiek obiektem. Każda instancja klasy współużytkuje swoje metody statyczne.

Zwykle metoda statyczna w interfejsie jest używana jako metody pomocnicze, podczas gdy metoda domyślna jest używana jako domyślna implementacja dla klas, które implementują ten interfejs.

Przykład:

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
źródło
1

Zgodnie z dokumentem JLS Java14 :

Metoda domyślna:

  • Jest to metoda instancji zadeklarowana w interfejsie z domyślnym modyfikatorem

  • Dostęp do niego jest możliwy tylko przez instancję klasy implementującej

  • Jego treść jest zawsze reprezentowana przez blok, który zapewnia domyślną implementację lub zachowanie dla dowolnej klasy implementującej bez zastępowania metody

  • Nigdy nie może być statyczne ani prywatne

Metoda statyczna:

  • Może zostać wywołany przez interfejs bez odniesienia do konkretnego obiektu, tak jak metody statyczne klasy

  • Metoda statyczna może być prywatna

  • Klasa implementująca nie może uzyskać dostępu do metody statycznej

Zrozummy to za pomocą poniższego przykładowego kodu:

            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
źródło
0

nie możemy wykonać, Interfacesample2.menthod3();ponieważ nie jest to metoda statyczna. Do wykonania method3()potrzebna jest instancja Interfacesample2interfejsu.

Proszę znaleźć następujący praktyczny przykład:

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");
    }
}
Premraj
źródło
0

Uruchomienie interfejsu Java 8 może mieć również metodę statyczną. Podobnie jak statyczna metoda klasy, statyczna metoda interfejsu może być wywołana przy użyciu nazwy interfejsu.

Przykład

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

Różnica między statyczną a domyślną metodą interfejsu polega na tym, że metoda domyślna obsługuje dziedziczenie, ale metoda statyczna nie. Domyślną metodę można zastąpić w dziedziczeniu interfejsu.

Oto dobra lektura o domyślnej metodzie interfejsu i metodzie statycznej. Domyślna metoda interfejsu w Javie 8

Rakesh Prajapati
źródło
0

Wszystkie dobre odpowiedzi tutaj. Chciałbym dodać jeszcze jedno praktyczne zastosowanie funkcji statycznej w interfejsie. Wskazówka pochodzi z książki - Effective Java, 3rd Edition autorstwa Joshua Bloch w rozdziale 2: Creating and Destroying Object.

Static functions can be used for static factory methods. 

Statyczne metody fabryczne to metody zwracające obiekt. Pracują jak konstruktor. W określonych przypadkach statyczna metoda fabryki zapewnia bardziej czytelny kod niż użycie konstruktora.

Cytat z książki - Effective Java, 3rd Edition autorstwa Joshua Bloch

Przed wersją Java 8 interfejsy nie mogły mieć metod statycznych. Zgodnie z konwencją statyczne metody fabryczne dla interfejsu o nazwie Type zostały umieszczone w nieinstanowalnej klasie towarzyszącej (pozycja 4) o nazwie Types.

Autor podaje przykład kolekcji, w których zaimplementowano taką statyczną metodę fabryczną. Sprawdzając kod, Josh Bloch może być postrzegany jako pierwszy autor klasy Kolekcje. Chociaż Kolekcje to klasa, a nie interfejs. Ale koncepcja nadal obowiązuje.

Na przykład Java Collections Framework ma czterdzieści pięć implementacji narzędziowych swoich interfejsów, zapewniając niezmodyfikowalne kolekcje, zsynchronizowane kolekcje i tym podobne. Prawie wszystkie te implementacje są eksportowane za pomocą statycznych metod fabrycznych w jednej nieinstanowalnej klasie (java.util.Collections). Wszystkie klasy zwróconych obiektów są niepubliczne.

Dalej wyjaśnia, że ​​API jest nie tylko mniejsze, ale także pomaga w czytelności kodu i łatwości API.

Zmniejsza się nie tylko większość API, ale także ciężar pojęciowy: liczba i stopień trudności koncepcji, które programiści muszą opanować, aby móc korzystać z API. Programista wie, że zwracany obiekt ma dokładnie API określone przez jego interfejs, więc nie ma potrzeby czytać dodatkowej dokumentacji klasy dla klasy implementacji.

Oto jedna z metod statycznych z klasy java.util.Collections:

public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
    return new UnmodifiableCollection<>(c);
}
Jay Rajput
źródło