Sự khác biệt giữa phương thức tĩnh và phương thức mặc định trong giao diện


107

Tôi đang tìm hiểu về các giao diện khi tôi nhận thấy rằng bây giờ bạn có thể xác định các phương thức tĩnh và mặc định trong một giao diện.

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

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

Vui lòng giải thích sự khác biệt của cả hai và nếu có ví dụ về thời điểm chúng tôi sử dụng điều này sẽ rất hay. Một chút nhầm lẫn trên Giao diện.


4
Bạn đã thử đọc các phương thức tĩnh trong hướng dẫn Java chưa?
Dawood ibn Kareem

1
Vì vậy, bạn đã bỏ lỡ phần về việc không bao giờ có thể ghi đè một phương thức tĩnh?
Dawood ibn Kareem

1
không hiểu giống nhau trên các giao diện
Vipin Menon

9
static method là một thành viên tĩnh của Giao diện, không thể bị ghi đè (như với lớp), phương thức mặc định là default implementationphương thức có thể bị ghi đè.
Shail016,

2
Chỉ tự hỏi: tại sao bạn không bao giờ chấp nhận một câu trả lời ở đây?
GhostCat

Câu trả lời:


116

Sự khác biệt giữa phương thức tĩnh và phương thức mặc định trong Java 8:

1) Các phương thức mặc định có thể được ghi đè trong lớp thực thi, trong khi phương thức tĩnh thì không thể .

2) Phương thức tĩnh chỉ thuộc về lớp Giao diện, vì vậy bạn chỉ có thể gọi phương thức tĩnh trên lớp Giao diện, không phải trên lớp triển khai Giao diện này, hãy xem:

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) Cả lớp và giao diện đều có thể có các phương thức tĩnh có cùng tên và không ghi đè các phương thức khác!

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
nhưng tại sao 'tĩnh'? nó phục vụ mục đích gì trong Java 8?
Shashank Vivek

4
Mục đích của từ khóa static không thay đổi - để xác định các thành viên cấp lớp: trường, phương thức, v.v. Trong Java 8, hành vi này đã được mở rộng thành Giao diện, vì vậy chúng trở nên giống với các lớp hơn và bây giờ có thể thay thế lớp trong hầu hết các tình huống.
ster

yea nhưng chúng ta vẫn có thể ẩn phương thức tĩnh giao diện thay vì ghi đè, .... tôi chỉ nghĩ rằng cả hai đều đáp ứng như nhau purpose( sử dụng một triển khai chung ) và giải quyết sự mơ hồ bằng cách implementing the logic again in subclass (ghi đè, ẩn ). lý do hợp lý duy nhất sẽ là do [các phương thức giao diện tĩnh không được kế thừa] ( stackoverflow.com/questions/25169175/… ) và do đó chúng tôi không thể gọi chúng bằng cá thể lớp con.
Amarnath Harish

29

Phương thức tĩnh là một phương thức áp dụng cho 'không gian tên' của lớp, có thể nói như vậy. Vì vậy, một staticphương thức foocủa giao diện Interfaceđược truy cập bởi Interface.foo(). Lưu ý rằng lệnh gọi hàm không áp dụng cho bất kỳ trường hợp cụ thể nào của giao diện.

Mặt khác, một triển khai mặc định bar, được gọi bởi

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

Một staticphương thức giao diện không thể biết về thisbiến, nhưng một triển khai mặc định có thể.


19

1. giải thích sự khác biệt của hai

Các phương thức giao diện tĩnh giống như các phương thức lớp tĩnh (ở đây chúng chỉ thuộc về Giao diện). Trong trường hợp các phương thức giao diện mặc định cung cấp default implementationcác phương thức giao diện (mà các lớp triển khai có thể có override)
Nhưng hãy nhớ trong trường hợp một lớp là implementing more than one interface with same defaultchữ ký phương thức thì lớp thực thineeds to override the default method

Bạn có thể tìm một ví dụ đơn giản bên dưới (có thể Tự làm cho các trường hợp khác nhau)

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. khi chúng ta sử dụng cái này sẽ rất hay.

Điều đó phụ thuộc vào tuyên bố vấn đề của bạn. Tôi sẽ nói các phương thức Mặc định rất hữu ích, nếu bạn cần triển khai giống nhau cho một phương thức trong đặc tả của mình trong tất cả các lớp trong hợp đồng đó, Hoặc nó có thể được sử dụng như Adaptercác lớp.

đây là một bài đọc hay: /software/233053/why-were-default-and-static-methods-added-to-interfaces-in-java-8-when-we-alread

cũng bên dưới oracle doc giải thích các phương thức mặc định & tĩnh để phát triển các giao diện hiện có:

Người dùng có các lớp triển khai giao diện được nâng cao với các phương thức mặc định hoặc tĩnh mới không phải sửa đổi hoặc biên dịch lại chúng để phù hợp với các phương thức bổ sung.

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


Tôi có một nghi ngờ. Có thể tạo một đối tượng của một giao diện? Mã của bạn có dòng này: I1 t = new I1 ()
Hackinet 27/10/18

@Hackinet vui lòng đọc nhận xét của java về tuyên bố đó. Vui lòng đọc thêm về các lớp học Ẩn danh. Hy vọng rằng sẽ giúp bạn.
Shail016,

12

Đây là quan điểm của tôi:

phương thức tĩnh trong giao diện:

  • Bạn có thể gọi nó trực tiếp (InterfacetA.staticMethod ())

  • Lớp phụ sẽ không thể ghi đè.

  • Lớp con có thể có phương thức trùng tên với staticMethod

phương pháp mặc định trong giao diện:

  • Bạn không thể gọi nó trực tiếp.

  • Lớp phụ sẽ có thể ghi đè nó

Lợi thế:

  • static Method: Bạn không cần tạo lớp riêng cho phương thức tiện ích.

  • Phương pháp mặc định: Cung cấp chức năng phổ biến trong phương thức mặc định.


8

Liên kết này có một số thông tin chi tiết hữu ích, đã liệt kê một vài trong số chúng ở đây.

các phương thức default & static đã làm cầu nối sự khác biệt giữa các giao diện và các lớp trừu tượng .

Các phương pháp mặc định của giao diện :

  • Nó giúp tránh các lớp tiện ích, chẳng hạn như tất cả các phương thức của lớp Collections có thể được cung cấp trong chính các giao diện.
  • Nó giúp mở rộng các giao diện mà không sợ phá vỡ các lớp thực thi.

Giao diện phương thức tĩnh :

  • Chúng là một phần của giao diện, chúng ta không thể sử dụng nó cho các đối tượng lớp thực thi.
  • Nó giúp cung cấp bảo mật bằng cách không cho phép các lớp thực thi ghi đè chúng.

Thích trích dẫn một tài liệu tham khảo hữu ích khác .


3

Các phương pháp mặc định của giao diện:

Nó giúp tránh các lớp tiện ích, chẳng hạn như tất cả các phương thức của lớp Collections có thể được cung cấp trong chính các giao diện.

Nó giúp mở rộng các giao diện mà không sợ phá vỡ các lớp thực thi.

Giao diện phương thức tĩnh:

Chúng là một phần của giao diện, chúng ta không thể sử dụng nó cho các đối tượng lớp thực thi.

Nó giúp cung cấp bảo mật bằng cách không cho phép các lớp thực thi ghi đè chúng.

Bây giờ phương pháp tĩnh cung cấp bảo mật như thế nào. Hãy xem một ví dụ.

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

    }
}

Ở đây obj.newMethod();in logic thực thi lớp, có nghĩa là chúng ta có thể thay đổi logic của phương thức đó bên trong lớp thực thi.

Nhưng obj.anotherNewMethod();in thực hiện lớp logic, nhưng không thay đổi thực hiện giao diện. Vì vậy, nếu bất kỳ logic mã hóa-giải mã nào được viết bên trong phương thức đó, bạn không thể thay đổi.


câu trả lời này có vẻ như nó đã đi đâu đó tốt, rồi đột nhiên bùng nổ! không có lời giải thích có ý nghĩa ở cuối. nhưng không thay đổi thực hiện giao diện điều này có nghĩa là gì?
Amarnath Harish

2

Theo Javadocs của Oracle: http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

Các phương thức mặc định cho phép bạn thêm chức năng mới vào giao diện của thư viện và đảm bảo tính tương thích nhị phân với mã được viết cho các phiên bản cũ hơn của các giao diện đó.

Phương thức tĩnh là một phương thức được liên kết với lớp mà nó được định nghĩa hơn là với bất kỳ đối tượng nào. Mọi thể hiện của lớp đều chia sẻ các phương thức tĩnh của nó.

Thông thường, phương thức tĩnh trong giao diện được sử dụng làm phương thức Trình trợ giúp trong khi phương thức mặc định được sử dụng làm phương thức triển khai mặc định cho các lớp triển khai giao diện đó.

Thí dụ:

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

Theo tài liệu Java14 JLS:

Phương pháp mặc định:

  • Nó là một phương thức thể hiện được khai báo trong một giao diện với công cụ sửa đổi mặc định

  • Nó chỉ có thể được truy cập bởi phiên bản của lớp triển khai

  • Phần thân của nó luôn được đại diện bởi một khối, khối này cung cấp triển khai hoặc hành vi mặc định cho bất kỳ lớp triển khai nào mà không cần ghi đè phương thức

  • Nó không bao giờ có thể là tĩnh hoặc riêng tư

Phương pháp tĩnh:

  • Nó có thể được gọi bằng giao diện mà không cần tham chiếu đến một đối tượng cụ thể, giống như các phương thức tĩnh của lớp

  • Phương thức tĩnh có thể là riêng tư

  • Lớp thực thi không thể truy cập phương thức tĩnh

Hãy hiểu nó với sự trợ giúp của mã ví dụ dưới đây:

            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

chúng ta không thể thực thi Interfacesample2.menthod3();vì nó không phải là phương thức tĩnh. Để thực thi, method3()chúng ta cần một phiên bản của Interfacesample2giao diện.

Vui lòng tìm ví dụ thực tế sau:

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

Khởi động giao diện Java 8 cũng có thể có phương thức tĩnh. Giống như phương thức tĩnh của một lớp, phương thức tĩnh của một giao diện có thể được gọi bằng tên Giao diện.

Thí dụ

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

Sự khác biệt giữa phương thức tĩnh và phương thức mặc định của giao diện là phương thức mặc định hỗ trợ kế thừa nhưng phương thức tĩnh thì không. Phương thức mặc định có thể được ghi đè trong giao diện kế thừa.

Đây là bài đọc tốt về phương thức mặc định giao diện và phương thức tĩnh. Phương pháp mặc định giao diện trong Java 8


0

Tất cả các câu trả lời tốt ở đây. Tôi muốn thêm một cách sử dụng thực tế khác của hàm tĩnh trong giao diện. Mẹo đến từ cuốn sách - Java hiệu quả, Tái bản lần thứ 3 của Joshua Bloch trong Chương 2: Tạo và phá hủy đối tượng.

Static functions can be used for static factory methods. 

Phương thức nhà máy tĩnh là các phương thức trả về một đối tượng. Chúng hoạt động giống như constructor. Trong các trường hợp cụ thể, phương thức static factory cung cấp mã dễ đọc hơn là sử dụng hàm tạo.

Trích dẫn từ sách - Java hiệu quả, Tái bản lần thứ 3 của Joshua Bloch

Trước Java 8, các giao diện không thể có các phương thức tĩnh. Theo quy ước, các phương thức nhà máy tĩnh cho một giao diện có tên là Kiểu được đặt trong một lớp đồng hành không bền (Mục 4) có tên là Kiểu.

Tác giả đưa ra một ví dụ về Bộ sưu tập nơi phương pháp nhà máy tĩnh như vậy được thực hiện. Kiểm tra mã, Josh Bloch có thể được xem là tác giả đầu tiên của lớp Collections. Mặc dù Bộ sưu tập là một lớp chứ không phải giao diện. Nhưng khái niệm vẫn được áp dụng.

Ví dụ: Java Collections Framework có 45 triển khai tiện ích cho các giao diện của nó, cung cấp các bộ sưu tập không thể sửa đổi, bộ sưu tập được đồng bộ hóa và những thứ tương tự. Gần như tất cả các triển khai này đều được xuất thông qua các phương thức của nhà máy tĩnh trong một lớp không thể thay đổi (java.util.Collections). Các lớp của các đối tượng được trả về đều là không công khai.

Hơn nữa, anh ấy giải thích rằng API không chỉ nhỏ hơn, nó giúp dễ đọc mã và API dễ dàng ..

Nó không chỉ là khối lượng lớn của API bị giảm đi mà là trọng lượng của khái niệm: số lượng và độ khó của các khái niệm mà lập trình viên phải nắm vững để sử dụng API. Lập trình viên biết rằng đối tượng trả về đã chính xác là API được chỉ định bởi giao diện của nó, vì vậy không cần phải đọc tài liệu lớp bổ sung cho lớp triển khai.

Đây là một trong những phương thức tĩnh từ lớp java.util.Collections:

public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
    return new UnmodifiableCollection<>(c);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.