인터페이스의 정적 메서드와 기본 메서드의 차이점


107

이제 인터페이스에서 정적 및 기본 메서드를 정의 할 수 있다는 것을 알았을 때 인터페이스를 통해 학습했습니다.

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

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

두 가지의 차이점을 친절하게 설명하고 언제 사용하는지에 대한 예가 있다면 좋을 것입니다. 인터페이스에 대해 약간 혼란스러워합니다.


4
자바 튜토리얼에서 정적 메소드를 읽어 보셨나요?
Dawood ibn Kareem

1
그래서 정적 메서드를 재정의 할 수 없다는 부분을 놓쳤습니까?
Dawood ibn Kareem

1
인터페이스에 동일한 이해 didnt는
비핀 메논에게

9
정적 메소드는 인터페이스의 정적 멤버이며 (클래스와 마찬가지로) default implementation재정의 될 수 없습니다. 기본 메서드는 재정의 될 수있는 메서드의입니다.
Shail016

2
그냥 궁금해 : 왜 여기서 대답을 받아들이지 않았습니까?
GhostCat

답변:


116

Java 8에서 정적 메소드와 기본 메소드의 차이점 :

1) 기본 방법이 될 수 있는 동안 정적이 클래스를 구현 오버라이드 (override) 할 수 없습니다 .

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에서 어떤 용도로 사용됩니까?
Shashank Vivek

4
정적 키워드의 목적은 변경되지 않았습니다. 클래스 레벨 멤버 (필드, 메소드 등)를 정의합니다. Java 8에서이 동작은 인터페이스로 확장되어 클래스와 더 유사 해졌고 이제 대부분의 시나리오에서 클래스를 대체 할 수 있습니다.
스팅거

그래도 우리는 여전히 재정의 대신 인터페이스 정적 메서드를 숨길 수 있습니다 .... 저는 둘 다 똑같은 것을 수행하고 purpose( 공통 구현 사용 ) implementing the logic again in subclass ( 재정의, 숨김 )에 의해 모호성을 해결 한다고 생각 합니다 . 유일한 현명한 이유는 [정적 인터페이스 메소드가 상속되지 않는] ( stackoverflow.com/questions/25169175/… ) 때문에 서브 클래스 인스턴스를 사용하여 호출 할 수 없기 때문입니다.
아마 나스 하 리쉬

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

또한 오라클 문서 아래에서는 기존 인터페이스를 발전시키기위한 기본 및 정적 방법을 설명합니다.

새로운 기본 또는 정적 메서드로 향상된 인터페이스를 구현하는 클래스가있는 사용자는 추가 메서드를 수용하기 위해이를 수정하거나 다시 컴파일 할 필요가 없습니다.

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


의심 스럽다. 인터페이스의 객체를 생성 할 수 있습니까? I1 t = 새로운 I1 () : 코드는이 라인이
Hackinet

@Hackinet은 그 진술에 대한 자바 주석을 친절하게 읽었습니다. 익명 클래스에 대해서도 읽어보십시오. 도움이 되었기를 바랍니다.
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

Oracle의 Javadocs에 따르면 : 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

여기에 모든 좋은 답변이 있습니다. 인터페이스에서 정적 함수의 또 다른 실용적인 사용법을 추가하고 싶습니다. 팁은 Chapter2 : Creating and Destroying Object에있는 Joshua Bloch의 저서-Effective Java, 3rd Edition에서 온 것입니다.

Static functions can be used for static factory methods. 

정적 팩토리 메서드는 객체를 반환하는 메서드입니다. 그들은 생성자처럼 작동합니다. 특정 경우에 정적 팩토리 메서드는 생성자를 사용하는 것보다 더 읽기 쉬운 코드를 제공합니다.

책에서 인용-Joshua Bloch의 효과적인 자바, 3 판

Java 8 이전에는 인터페이스에 정적 메서드가 없었습니다. 관례 적으로 Type이라는 인터페이스에 대한 정적 팩토리 메서드는 Types라는 이름의 인스턴스화 할 수없는 동반 클래스 (항목 4)에 배치되었습니다.

Author는 이러한 정적 팩토리 메서드가 구현 된 컬렉션의 예를 제공합니다. 코드를 확인하면 Josh Bloch는 Collections 클래스의 첫 번째 작성자로 볼 수 있습니다. Collections는 인터페이스가 아닌 클래스이지만. 그러나 개념은 여전히 ​​적용됩니다.

예를 들어, Java Collections Framework에는 수정 불가능한 컬렉션, 동기화 된 컬렉션 등을 제공하는 45 개의 인터페이스 유틸리티 구현이 있습니다. 이러한 거의 모든 구현은 인스턴스화 할 수없는 하나의 클래스 (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);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.