itsource

인터페이스에는 스태틱메서드가 없지만 스태틱필드와 내부 클래스는 정상인 이유는 무엇입니까?[Java8 이전]

mycopycode 2022. 11. 24. 20:46
반응형

인터페이스에는 스태틱메서드가 없지만 스태틱필드와 내부 클래스는 정상인 이유는 무엇입니까?[Java8 이전]

인터페이스 내에서 스태틱메서드를 정의할 수 없는 이유에 대해서는 몇 가지 질문이 있습니다만, 그 어느 것도 기본적인 부정합에 대응하지 않습니다.왜 스태틱메서드는 정의할 수 있지만 스태틱메서드는 정의할 수 없는 것입니까?

정적 내부 타입은 아마도 공정한 비교가 되지 않을 것이다. 왜냐하면 그것은 단지 새로운 클래스를 생성하는 통사적인 설탕이기 때문이다. 하지만 왜 방법은 아닌 필드를 만들었을까?

인터페이스 내의 정적 메서드에 대한 반대 논거는 JVM이 사용하는 가상 테이블 해결 전략을 깨는 것이지만, 이는 정적 필드에도 동일하게 적용되어야 하지 않나요? 즉, 컴파일러가 이를 인라인화할 수 있습니다.

일관성은 제가 원하는 것입니다.Java는 인터페이스 내에서 어떤 형식의 통계도 지원하지 않거나 일관되게 허용해야 합니다.

Java 7의 인터페이스로 스태틱메서드를 허용하는 공식 제안이 작성되었습니다.이 제안은 Project Coin에서 이루어집니다.

제 개인적인 생각은 그것이 좋은 생각이라는 것입니다.구현에는 기술적인 어려움이 없으며 매우 논리적이고 합리적인 작업입니다.Project Coin에는 자바 언어의 일부가 되지 않기를 바라는 제안들이 몇 가지 있지만, 이것은 많은 API를 정리할 수 있는 제안입니다.예를 들어 클래스에는 스태틱메서드가 있어List 현 implement implement음음음음음음음음음음음음음음음음 the the the the the the implement implement 에 포함될 수 있습니다.List인터페이스입니다.


업데이트: Java Posse Podcast #234에서 Joe D'arcy는 제안서를 간단히 언급하면서 "복잡하다"며 Project Coin에 들어갈 수 없을 것이라고 말했다.


업데이트: Java 7용 Project Coin에는 포함되지 않았지만 Java 8은 인터페이스에서 정적 기능을 지원합니다.

저는 이 이론과 함께 제 애완견 이론을 따르겠습니다. 이 경우 일관성의 결여는 디자인이나 필요성보다는 편의성의 문제라는 것입니다. 왜냐하면 저는 그 둘 중 하나라는 설득력 있는 주장을 듣지 못했기 때문입니다.

스태틱 필드는 (a) JDK 1.0에 존재했기 때문에 JDK 1.0에서 많은 의심스러운 결정이 내려졌습니다.또 (b) 인터페이스의 스태틱 최종 필드는 당시 Java가 상수에 가장 가까운 필드입니다.

인터페이스 내의 정적 내부 클래스는 순수한 구문설탕이기 때문에 허용되었습니다. 내부 클래스는 부모 클래스와 실제로 아무런 관련이 없습니다.

따라서 정적인 방법은 특별한 이유가 없기 때문에 허용되지 않으며, 일관성이 부족하여 현상을 바꿀 수 없습니다.

물론 이것은 미래의 JLS 버전에서는 아무것도 파손하지 않고 허용될 수 있습니다.

인터페이스에 스태틱 방식을 선언하는 것은 의미가 없습니다.통상의 콜 MyInterface.staticMethod()에서는 실행할 수 없습니다.(편집:마지막 문장이 일부 사용자를 혼란스럽게 했기 때문에 MyClass.staticMethod()를 호출하면 MyClass에서 staticMethod가 정확하게 구현됩니다.MyClass가 인터페이스일 경우 이 구현은 존재할 수 없습니다.)구현 클래스 MyImplementor.staticMethod()를 지정하여 호출하는 경우 실제 클래스를 알아야 합니다.따라서 인터페이스가 클래스를 포함하든 포함하지 않든 상관없습니다.

더 중요한 것은 스태틱메서드는 덮어쓰지 않으며, 다음 작업을 수행하려고 하면 다음과 같습니다.

MyInterface var = new MyImplementingClass();
var.staticMethod();

static 규칙에는 선언된 유형의 var에서 정의된 메서드가 실행되어야 한다고 명시되어 있습니다.이것은 인터페이스이기 때문에 불가능합니다.

물론 static 키워드는 항상 메서드에서 삭제할 수 있습니다.모든 게 정상으로 작동할 겁니다.인스턴스 메서드에서 호출된 경우 경고를 일부 억제해야 할 수 있습니다.

아래의 코멘트에 답하려면 , 「result=My」를 실행할 수 없는 이유.Interface.staticMethod()"는 MyInterface에서 정의된 메서드 버전을 실행해야 합니다.그러나 MyInterface에는 버전이 정의되어 있지 않습니다.이것은 인터페이스이기 때문입니다.정의상 코드가 없습니다.

인터페이스의 목적은 구현을 제공하지 않고 계약을 정의하는 것입니다.따라서 스태틱 메서드를 사용할 수 없습니다.스태틱 메서드를 덮어쓸 수 없기 때문에 인터페이스에 이미 구현되어 있어야 합니다.스태틱한 "만"final fields기본적으로는 상수(1.5+에서는 인터페이스에도 enum을 설정할 수 있습니다).이 상수는 매직 넘버 없이 인터페이스를 정의하는 데 도움이 됩니다.

BTW를 으로 지정할 static final스태틱 최종 필드만 허용되므로 인터페이스의 필드 수식자.

이것은 오래된 이야기지만, 이것은 모두에게 매우 중요한 질문이다.오늘에야 알게 되었기 때문에 좀 더 알기 쉽게 설명하려고 합니다.

인터페이스의 주된 목적은 구현할 수 없는 것을 제공하는 것입니다.따라서 이 인터페이스가

허용되는 정적 메서드

그런 다음 interfaceName.staticMethodName()사용하여 이 메서드를 호출할 수 있지만 구현되지 않은 메서드로 아무것도 포함되어 있지 않습니다.따라서 정적 방법을 허용해도 소용이 없습니다.그러므로 그들은 이것을 전혀 제공하지 않는다.

static 필드는 허용됩니다.

필드는 구현이 불가능하기 때문에 구현 가능, 즉 현장에서 논리적 연산을 수행할 수 없으며 현장에서 연산을 수행할 수 있습니다.따라서 필드의 동작을 변경하지 않기 때문에 필드 동작이 허용됩니다.

내부 클래스는 허용됩니다.

컴파일 후 InterfaceName$같이 내부 클래스의 다른 클래스 파일이 생성되므로 내부 클래스가 허용됩니다.InnerClassName.class는 기본적으로 다른 엔티티에 모두 실장하지만 인터페이스에는 실장하지 않습니다.그래서 이너 클래스에서의 구현이 제공됩니다.

이게 도움이 됐으면 좋겠어요.

실제로 정적 방법으로부터 이익을 얻을 수 있는 이유가 있을 수 있습니다.이것들은, 인터페이스를 실장하는 클래스의 공장 방식으로서 사용할 수 있습니다.예를 들어 Collection 인터페이스와 Collections 클래스가 openjdk에 있는 이유입니다.따라서 항상 그렇듯이 다른 클래스에 정적 메서드의 "네임스페이스" 역할을 하는 개인 생성자를 제공합니다.

Java 5 이전에는 스태틱필드의 일반적인 용도는 다음과 같습니다.

interface HtmlConstants {
    static String OPEN = "<";
    static String SLASH_OPEN = "</";
    static String CLOSE = ">";
    static String SLASH_CLOSE = " />";
    static String HTML = "html";
    static String BODY = "body";
    ...
}

public class HtmlBuilder implements HtmlConstants { // implements ?!?
    public String buildHtml() {
       StringBuffer sb = new StringBuffer();
       sb.append(OPEN).append(HTML).append(CLOSE);
       sb.append(OPEN).append(BODY).append(CLOSE);
       ...
       sb.append(SLASH_OPEN).append(BODY).append(CLOSE);
       sb.append(SLASH_OPEN).append(HTML).append(CLOSE);
       return sb.toString();
    }
}

이는 Html Builder가 각 상수를 한정할 필요가 없다는 것을 의미하며, Html Constants 대신 OPEN을 사용할 수 있게 되었습니다.열려 있다

이런 식으로 도구를 사용하는 것은 궁극적으로 혼란스럽다.

Java 5에서는 Import static 구문을 사용하여 동일한 효과를 얻을 수 있습니다.

private final class HtmlConstants {
    ...
    private HtmlConstants() { /* empty */ }
}

import static HtmlConstants.*;
public class HtmlBuilder { // no longer uses implements
    ...
}

인터페이스에 스태틱메서드가 없는 진짜 이유는 자바 언어 설계자가 그렇게 하고 싶지 않았기 때문입니다.기술적 관점에서 보면 그들을 허용하는 것이 말이 될 것이다.결국 추상적인 수업도 그것들을 가질 수 있다.인터페이스가 정적 메서드를 가지고 있는 경우 바이트 코드를 "수공"할 수 있고 메서드를 호출하거나 인터페이스를 정상적으로 사용하는 데 문제가 없을 것으로 추측하지만 테스트하지 않았습니다.

나는 왜 정적 방식을 사용하는지 종종 궁금해 한다.용도는 있습니다만, 패키지/네임스페이스 레벨의 메서드는, 스태틱한 메서드의 80을 커버합니다.

다음과 같은 두 가지 주요 이유가 생각납니다.

  1. Java의 스태틱메서드는 서브클래스에 의해 덮어쓸 수 없습니다.이것은 스태틱필드보다 메서드에 훨씬 큰 문제입니다.실제로는 서브클래스의 필드를 오버라이드하고 싶지도 않지만 항상 메서드를 오버라이드합니다.따라서 스태틱 메서드를 사용하면 인터페이스를 구현하는 클래스가 그 메서드의 자체 구현을 제공할 수 없게 되어 인터페이스를 사용하는 목적이 크게 상실됩니다.

  2. 인터페이스에는 코드가 없어야 합니다.그게 추상 클래스가 필요한 이유입니다.인터페이스의 요점은 모든 객체에 특정 메서드세트가 있을 가능성이 있는 비관련 객체에 대해 설명할 수 있도록 하는 것입니다.실제로 이러한 방식의 실장을 제공하는 것은, 인터페이스의 목적의 범위를 넘는 것입니다.

스태틱 메서드는 클래스에 관련지어져 있습니다.Java 에서는 인터페이스는 엄밀히 말하면 클래스가 아니라 타입이지만 클래스가 아닙니다(따라서 키워드가 구현되어 인터페이스가 오브젝트를 확장하지 않습니다).인터페이스는 클래스가 아니기 때문에 실제로 연결할 클래스가 없기 때문에 스태틱메서드를 가질 수 없습니다.

InterfaceName.class를 호출하여 인터페이스에 대응하는 Class Object를 얻을 수 있지만 Class 클래스는 특히 Java 응용 프로그램의 클래스 및 인터페이스를 나타내는 것을 나타냅니다.단, 인터페이스 자체는 클래스로 취급되지 않기 때문에 스태틱메서드를 부가할 수 없습니다.

인터페이스에 선언할 수 있는 것은 static final 필드뿐입니다('public' 키워드를 포함하지 않아도 public 메서드와 거의 비슷하지만 static 필드는 키워드를 포함하거나 포함하지 않아도 final입니다).

이는 값일 뿐이며 컴파일 시 사용되는 모든 위치에 그대로 복사되므로 실행 시 정적 필드를 실제로 "호출"하는 일은 없습니다.정적 메서드를 갖는 것은 구현 없이 인터페이스를 호출해야 하므로 동일한 의미론을 가지지 않습니다. Java는 이를 허용하지 않습니다.

그 이유는 그 수식자를 명시적으로 선언하든 아니든 인터페이스에 정의되어 있는 모든 메서드가 추상적이기 때문입니다.정적 메서드는 재정의할 수 없으므로 추상 정적 메서드는 수식자의 사용 가능한 조합이 아닙니다.

인터페이스가 스태틱필드를 허가하는 이유저는 "특징"으로 여겨야 할 느낌이 있습니다.생각할 수 있는 유일한 방법은 인터페이스 구현에 관심이 있는 그룹 상수입니다.

나는 일관성이 더 나은 접근법이었다는 것에 동의한다.인터페이스에는 스태틱멤버를 사용할 수 없습니다.

정적 메서드는 객체를 생성하지 않고 접근할 수 있으며, 인터페이스는 프로그래머가 구현된 클래스가 아닌 인터페이스 메서드를 직접 사용하는 것을 제한하는 오브젝트를 생성할 수 없다고 생각합니다.다만, 인터페이스에 스태틱 방식을 정의하면, 실장하지 않고 직접 액세스 할 수 있습니다.따라서 스태틱 메서드는 인터페이스에서는 사용할 수 없습니다.나는 일관성이 문제가 되어서는 안 된다고 생각한다.

Java 1.8 인터페이스 스태틱메서드는 인터페이스 메서드에만 표시됩니다.InterfaceExample 클래스에서 methodSta1() 메서드를 삭제하면 InterfaceExample 객체에 사용할 수 없습니다.단, 다른 스태틱메서드와 마찬가지로 클래스 이름을 사용하여 인터페이스 스태틱메서드를 사용할 수 있습니다.예를 들어 유효한 문장은 exp1 입니다.methodSta1();

따라서 아래 예를 보면 1) Java interface static 메서드는 인터페이스의 일부이므로 구현 클래스 오브젝트에 사용할 수 없습니다.

2) Java interface static 메서드는 null check, collection sorting, log 등의 유틸리티 메서드를 제공하는 데 적합합니다.

3) Java interface static method는 구현 클래스(InterfaceExample)에 의한 덮어쓰기를 허용하지 않음으로써 보안 제공에 도움이 됩니다.

4) 오브젝트 클래스의 메서드에 인터페이스 스태틱메서드를 정의할 수 없습니다.이 스태틱메서드는 인스턴스 메서드를 오브젝트에서 숨길 수 없습니다.라고 하는 컴파일러 에러가 표시됩니다.이는 Java에서는 허용되지 않기 때문입니다.오브젝트는 모든 클래스의 기본 클래스이기 때문에 하나의 클래스 수준의 정적 메서드와 동일한 시그니처를 가진 다른 인스턴스 메서드를 가질 수 없습니다.

5) Java interface static 메서드를 사용하여 Collections 등의 유틸리티 클래스를 삭제하고 모든 스태틱 메서드를 해당 인터페이스로 이동하여 쉽게 찾을 수 있습니다.

public class InterfaceExample implements exp1 {

    @Override
    public void method() {
        System.out.println("From method()");
    }

    public static void main(String[] args) {
        new InterfaceExample().method2();
        InterfaceExample.methodSta2();      //  <---------------------------    would not compile
        // methodSta1();                        //  <---------------------------    would not compile
        exp1.methodSta1();
    }

    static void methodSta2() {          //          <-- it compile successfully but it can't be overridden in child classes
        System.out.println("========= InterfaceExample :: from methodSta2() ======");
    }
}


interface exp1 {

    void method();
    //protected void method1();         //          <--      error
    //private void method2();           //          <--      error
    //static void methodSta1();         //          <--      error it require body in java 1.8

    static void methodSta1() {          //          <-- it compile successfully but it can't be overridden in child classes
        System.out.println("========= exp1:: from methodSta1() ======");
    }

    static void methodSta2() {          //          <-- it compile successfully but it can't be overridden in child classes
        System.out.println("========= exp1:: from methodSta2() ======");
    }

    default void method2() { System.out.println("---  exp1:: from method2() ---");}
    //synchronized default void method3() { System.out.println("---");}             // <-- Illegal modifier for the interface method method3; only public, abstract, default, static 
                                                                                // and strictfp are permitted
    //final default void method3() { System.out.println("---");} //             <--      error
}

언급URL : https://stackoverflow.com/questions/129267/why-no-static-methods-in-interfaces-but-static-fields-and-inner-classes-ok-pr

반응형