Arayüzde statik ve varsayılan yöntemler arasındaki fark


107

Artık bir arayüzde statik ve varsayılan yöntemleri tanımlayabileceğinizi fark ettiğimde arayüzler aracılığıyla öğreniyordum.

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

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

Lütfen ikisinin farkını açıklayın ve ayrıca bunu ne zaman kullanacağımızla ilgili bir örnek varsa iyi olur. Arayüzlerde biraz karışık.


4
Java eğitiminde statik yöntemleri okumayı denediniz mi?
Dawood ibn Kareem

1
Yani, statik bir yöntemi geçersiz kılamamakla ilgili kısmı kaçırdınız mı?
Dawood ibn Kareem

1
arayüzlerde aynı şeyi anlamadım
Vipin Menon

9
statik yöntem Arayüzün statik bir üyesidir, geçersiz kılınamaz (sınıfta olduğu gibi), varsayılan yöntem, default implementationgeçersiz kılınabilecek bir yöntemin yöntemidir.
Shail016

2
Merak ediyorum: neden burada bir cevabı hiç kabul etmediniz?
GhostCat

Yanıtlar:


116

Java 8'de statik ve varsayılan yöntemler arasındaki farklar:

1) Varsayılan yöntemler , sınıfın uygulanmasında geçersiz kılınabilirken statik olamaz .

2) Statik yöntem yalnızca Arabirim sınıfına aittir , bu nedenle bu Arabirimi uygulayan sınıfta değil, yalnızca Arabirim sınıfında statik yöntemi çağırabilirsiniz, bkz:

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) Hem sınıf hem de arayüz aynı ada sahip statik yöntemlere sahip olabilir ve hiçbiri diğerini geçersiz kılmaz!

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
ama neden 'durağan'? Java 8'de hangi amaca hizmet eder?
Shashank Vivek

4
Statik anahtar kelimenin amacı değişmez - sınıf düzeyindeki üyeleri tanımlamak için: alanlar, yöntemler vb. Java 8'de bu davranış Arabirimler'e genişletildi, böylece sınıflara daha çok benziyorlar ve artık çoğu senaryoda sınıfın yerini alabilirler.
stinger

evet, ancak arayüz statik yöntemini geçersiz kılmak yerine gizleyebiliriz, .... Sadece ikisinin de aynı şeyi gerçekleştirdiğini purpose( ortak bir uygulama kullanın ) ve belirsizliği implementing the logic again in subclass ( geçersiz kılma, gizleme ) çözdüğünü düşünüyorum . tek mantıklı neden, [statik arayüz yöntemlerinin miras alınmaması] ( stackoverflow.com/questions/25169175/… ) nedeniyledir ve bu nedenle onları alt sınıf örneği kullanarak çağıramayız.
amarnath harish

29

Statik yöntem, tabiri caizse 'ad alanı' sınıfı için geçerli olan bir yöntemdir. Yani bir arayüz staticyöntemine erişilir . İşlev çağrısının , arabirimin belirli herhangi bir örneği için geçerli olmadığını unutmayın .fooInterfaceInterface.foo()

barÖte yandan varsayılan bir uygulama şu şekilde adlandırılır:

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

Bir staticarabirim yöntemi thisdeğişkeni bilemez , ancak varsayılan bir uygulama olabilir.


19

1. ikisinin farkını açıklayın

Statik arabirim yöntemleri, statik sınıf yöntemlerine benzer (burada yalnızca Arabirime aittirler). Varsayılan arabirim yöntemleri arabirim yöntemlerini sağlarken default implementation(sınıfları uygulamak olabilir override)
Ancak, bir sınıfın implementing more than one interface with same defaultyöntem imzası olması durumunda uygulama sınıfının olduğunu unutmayın.needs to override the default method

Aşağıda basit bir örnek bulabilirsiniz (farklı durumlar için DIY yapabilirsiniz)

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. Bunu ne zaman kullanacağımız güzel olurdu.

Bu, sorun ifadenize bağlıdır. Varsayılan yöntemlerin yararlı olduğunu söyleyebilirim, eğer belirtiminizdeki bir yöntem için o sözleşmedeki tüm sınıflarda aynı uygulamaya ihtiyacınız varsa veya sınıflar gibi kullanılabilir Adapter.

iyi bir okuma: /software/233053/why-were-default-and-static-methods-added-to-interfaces-in-java-8-when-we-alread

ayrıca aşağıdaki oracle belgesi, mevcut arayüzleri geliştirmek için varsayılan ve statik yöntemleri açıklamaktadır:

Yeni varsayılan veya statik yöntemlerle geliştirilmiş arabirimleri uygulayan sınıflara sahip kullanıcıların, ek yöntemleri barındırmak için bunları değiştirmesi veya yeniden derlemesi gerekmez.

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


Kuşkum var. Bir arayüz nesnesi yaratmak mümkün müdür? Kodunuzda şu satır var: I1 t = new I1 ()
Hackinet

@Hackinet nazikçe bu ifadenin üzerindeki java yorumunu okuyun. Lütfen Anonim sınıfları da okuyun. Umarım bu size yardımcı olur.
Shail016

12

İşte benim görüşüm:

arayüzde statik yöntem :

  • Doğrudan çağırabilirsiniz (InterfacetA.staticMethod ())

  • Alt sınıf geçersiz kılınamaz.

  • Alt sınıf, staticMethod ile aynı ada sahip bir yönteme sahip olabilir

arayüzde varsayılan yöntem :

  • Doğrudan arayamazsınız.

  • Alt sınıf, onu geçersiz kılabilir

Avantaj:

  • statik Yöntem: Yardımcı yöntem yöntemi için ayrı bir sınıf oluşturmanıza gerek yoktur.

  • varsayılan Yöntem: Varsayılan yöntemde ortak işlevselliği sağlayın.


8

Bu bağlantı bazı yararlı bilgiler içeriyor, bunlardan birkaçını burada listeledik.

varsayılan ve statik yöntemler arayüzler ve soyut sınıflar arasındaki farkları ortadan kaldırmıştır .

Arayüz varsayılan yöntemleri:

  • Tüm Collections sınıfı yöntemi arabirimlerin kendisinde sağlanabildiği gibi, yardımcı sınıflardan kaçınmaya yardımcı olur.
  • Uygulama sınıflarını kırma korkusu olmadan arayüzlerin genişletilmesine yardımcı olur.

Arayüz statik yöntemleri:

  • Arabirimin bir parçasıdırlar, sınıf nesnelerini uygulamak için kullanamayız.
  • Uygulama sınıflarının onları geçersiz kılmasına izin vermeyerek güvenliği sağlamaya yardımcı olur.

Başka bir faydalı referanstan alıntı yapmak gibi .


3

Arayüz varsayılan yöntemleri:

Tüm Collections sınıfı yöntemi arabirimlerin kendisinde sağlanabildiği gibi, yardımcı sınıflardan kaçınmaya yardımcı olur.

Uygulama sınıflarını kırma korkusu olmadan arayüzlerin genişletilmesine yardımcı olur.

Arayüz statik yöntemleri:

Arabirimin bir parçasıdırlar, sınıf nesnelerini uygulamak için kullanamayız.

Uygulama sınıflarının onları geçersiz kılmasına izin vermeyerek güvenliği sağlamaya yardımcı olur.

Şimdi statik yöntem nasıl güvenlik sağlıyor. Bir örnek görelim.

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

    }
}

Buraya obj.newMethod(); baskı sınıfı uygulama mantığı, bu yöntemin mantığını uygulama sınıfı içinde değiştirebileceğimiz anlamına gelir.

Ancak obj.anotherNewMethod();yazdırma sınıfı uygulama mantığı, ancak arayüz uygulamasını değiştirmedi. Dolayısıyla, bu yöntemin içinde yazılmış herhangi bir şifreleme-şifre çözme mantığı varsa, değiştiremezsiniz.


bu cevap iyi bir yere gidiyormuş gibi görünüyordu, sonra aniden patlama! sonunda anlamlı bir açıklama yok. ancak değiştirilmemiş arayüz uygulaması bu ne anlama geliyor?
amarnath harish

2

Oracle'ın Javadocs'a göre: http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

Varsayılan yöntemler, kitaplıklarınızın arabirimlerine yeni işlevler eklemenize ve bu arabirimlerin eski sürümleri için yazılan kodla ikili uyumluluk sağlamanıza olanak tanır.

Statik yöntem, herhangi bir nesne yerine tanımlandığı sınıfla ilişkili bir yöntemdir. Sınıfın her örneği statik yöntemlerini paylaşır.

Normalde, arabirimdeki statik yöntem Yardımcı yöntemler olarak kullanılırken, varsayılan yöntem bu arabirimi uygulayan sınıflar için varsayılan bir uygulama olarak kullanılır.

Misal:

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

Gereğince Java14 JLS doc:

Varsayılan Yöntem:

  • Varsayılan değiştiriciyle bir arabirimde bildirilen bir örnek yöntemidir.

  • Yalnızca uygulama sınıfının örneği tarafından erişilebilir

  • Gövdesi her zaman, yöntemi geçersiz kılmadan herhangi bir uygulama sınıfı için varsayılan bir uygulama veya davranış sağlayan bir blokla temsil edilir.

  • Asla statik veya özel olamaz

Statik Yöntem:

  • Tıpkı sınıf statik yöntemleri gibi, belirli bir nesneye referans olmadan arabirim tarafından çağrılabilir.

  • Statik yöntem özel olabilir

  • Uygulama sınıfı statik yönteme erişemez

Aşağıdaki örnek kod yardımıyla anlayalım:

            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

Biz yürütemediğinden Interfacesample2.menthod3();statik bir yöntem değildir çünkü. Yürütmek için method3()bir örneğine ihtiyacımız varInterfacesample2 arayüz .

Lütfen aşağıdaki pratik örneği bulun:

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 arayüzünün başlatılması da statik yönteme sahip olabilir. Bir sınıfın statik yöntemi gibi, bir arabirimin statik yöntemi de Arabirim adı kullanılarak çağrılabilir.

Misal

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

Statik ve varsayılan arabirim yöntemi arasındaki fark, varsayılan yöntemin devralmayı desteklemesidir, ancak statik yöntem desteklemez. Varsayılan yöntem, arayüz devralmada geçersiz kılınabilir.

Burada arayüz varsayılan yöntemi ve statik yöntem hakkında iyi bir okuma bulabilirsiniz. Java 8'de Arayüz Varsayılan Yöntemi


0

Buradaki tüm iyi cevaplar. Arayüzde statik fonksiyonun başka bir pratik kullanımını eklemek istiyorum. İpucu, Bölüm 2: Creating and Destroying Object'teki - Effective Java, 3rd Edition, Joshua Bloch adlı kitaptan geliyor.

Static functions can be used for static factory methods. 

Statik fabrika yöntemi, bir nesneyi döndüren yöntemlerdir. Yapıcı gibi çalışırlar. Belirli durumlarda, statik fabrika yöntemi, yapıcı kullanmaktan daha okunabilir kod sağlar.

Kitaptan alıntı - Effective Java, 3rd Edition by Joshua Bloch

Java 8'den önce arayüzlerin statik yöntemleri olamazdı. Kural olarak, Type adlı bir arabirim için statik fabrika yöntemleri, Türler adlı bir tamamlayıcı sınıfa (Öğe 4) yerleştirildi.

Yazar, böyle bir statik fabrika yönteminin uygulandığı bir Koleksiyonlar örneği verir. Kodu kontrol ederek Josh Bloch, Koleksiyonlar sınıfının ilk yazarı olarak görülebilir. Koleksiyonlar bir sınıf olmasına rağmen arayüz değil. Ancak konsept hala geçerli.

Örneğin, Java Collections Framework, değiştirilemeyen koleksiyonlar, senkronize edilmiş koleksiyonlar ve benzerleri sağlayan, kendi arayüzlerinde kırk beş yardımcı uygulama uygulamasına sahiptir. Bu uygulamaların neredeyse tamamı, sabit fabrika yöntemleriyle tek bir sabitlenemez sınıfta (java.util.Collections) dışa aktarılır. Döndürülen nesnelerin sınıflarının tümü kamuya açık değildir.

Ayrıca, API'nin yalnızca daha küçük olmadığını, kod okunabilirliğine ve API kolaylığına yardımcı olduğunu da açıklıyor.

Azaltılan sadece API'nin büyük kısmı değil, aynı zamanda kavramsal ağırlık: API'yi kullanmak için programcıların ustalaşması gereken kavramların sayısı ve zorluğu. Programcı, döndürülen nesnenin tam olarak arabirimi tarafından belirtilen API'ye sahip olduğunu bilir, bu nedenle uygulama sınıfı için ek sınıf belgelerini okumaya gerek yoktur.

İşte java.util.Collections sınıfındaki statik yöntemlerden biri:

public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
    return new UnmodifiableCollection<>(c);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.