프로그래밍 언어/JAVA

Java 인터페이스에서 static 메소드를 정의 하는 방법

Rateye 2021. 12. 6. 10:01
728x90
반응형
질문 : Java 인터페이스에서 정적 메소드를 정의 할 수없는 이유는 무엇입니까?

편집 : Java 8부터 이제 인터페이스에서 정적 메서드가 허용됩니다.

다음은 그 예입니다.

public interface IXMLizable<T>
{
  static T newInstanceFromXML(Element e);
  Element toXMLElement();
}

물론 이것은 작동하지 않습니다. 하지만 왜 안돼?

가능한 문제 중 하나는 전화를 걸면 어떻게되는지입니다.

IXMLizable.newInstanceFromXML(e);

이 경우 빈 메서드 (예 : {})를 호출해야한다고 생각합니다. 모든 하위 클래스는 정적 메서드를 구현해야하므로 정적 메서드를 호출 할 때 모두 괜찮습니다. 그렇다면 왜 이것이 가능하지 않습니까?

편집 : 나는 "왜냐하면 Java가 그렇기 때문에"보다 더 깊은 대답을 찾고 있다고 생각합니다.

정적 메서드를 덮어 쓸 수없는 특별한 기술적 이유가 있습니까? 즉, Java 디자이너가 인스턴스 메서드를 재정의 할 수 있지만 정적 메서드가 아닌 이유는 무엇입니까?

편집 : 내 디자인의 문제는 인터페이스를 사용하여 코딩 규칙을 적용하려고한다는 것입니다.

즉, 인터페이스의 목표는 두 가지입니다.

  1. IXMLizable 인터페이스를 사용하여이를 구현하는 클래스를 XML 요소로 변환 할 수 있기를 원합니다 (다형성을 사용하여 잘 작동 함).
  2. IXMLizable 인터페이스를 구현하는 클래스의 새 인스턴스를 만들려는 경우 항상 newInstanceFromXML (Element e) 정적 생성자가 있다는 것을 알 수 있습니다.

 

 

인터페이스에 주석을 추가하는 것 외에 이를 보장하는 다른 방법이 있습니까?

답변

Java 8은 정적 인터페이스 메서드를 허용합니다.

Java 8에서 인터페이스는 정적 메소드를 가질 수 있습니다. 또한 구체적인 인스턴스 메서드를 가질 수 있지만 인스턴스 필드는 가질 수 없습니다.

여기에는 두 가지 질문이 있습니다.

  1. 옛날에는 인터페이스에 정적 메서드를 포함할 수 없었던 이유가 무엇입니까?
  2. 정적 메서드를 재정의할 수 없는 이유는 무엇입니까?

인터페이스의 정적 메서드

이전 버전에서는 인터페이스가 정적 메서드를 가질 수 없었던 강력한 기술적 이유가 없었습니다. 이것은 중복 질문 의 포스터에 의해 잘 요약됩니다. 정적 인터페이스 메소드는 처음에는 작은 언어 변경 으로 간주되었으며 Java 7에 추가 하라는 공식 제안 이 있었지만 예기치 않은 합병증으로 인해 나중에 삭제되었습니다.

마지막으로 Java 8은 정적 인터페이스 메소드와 기본 구현으로 재정의 가능한 인스턴스 메소드를 도입했습니다. 그래도 인스턴스 필드를 가질 수 없습니다. 이러한 기능은 람다 식 지원의 일부이며 JSR 335의 Part H에서 자세한 내용을 읽을 수 있습니다.

두 번째 질문에 대한 답은 좀 더 복잡합니다.

정적 메서드는 컴파일 타임에 확인할 수 있습니다. 동적 디스패치는 컴파일러가 개체의 구체적인 유형을 결정할 수 없으므로 호출 할 메서드를 확인할 수없는 인스턴스 메서드에 적합합니다. 그러나 정적 메서드를 호출하려면 클래스가 필요 하며이 클래스는 컴파일 타임에 정적으로 알려지기 때문에 동적 디스패치가 필요하지 않습니다.

여기에서 무슨 일이 일어나고 있는지 이해하려면 인스턴스 메서드의 작동 방식에 대한 약간의 배경 지식이 필요합니다. 실제 구현은 상당히 다르지만 동작을 정확하게 관찰 한 모델 인 메서드 디스패치에 대한 제 개념을 설명하겠습니다.

각 클래스에 메서드 서명 (이름 및 매개 변수 유형)을 실제 코드 청크에 매핑하여 메서드를 구현하는 해시 테이블이 있다고 가정합니다. 가상 머신은 인스턴스에서 메서드를 호출하려고 할 때 해당 클래스의 개체를 쿼리하고 클래스의 테이블에서 요청 된 서명을 찾습니다. 메소드 본문이 발견되면 호출됩니다. 그렇지 않으면 클래스의 부모 클래스가 얻어지고 거기에서 조회가 반복됩니다. 메서드를 찾거나 상위 클래스가 더 이상 없을 때까지 진행되어 NoSuchMethodError 합니다.

수퍼 클래스와 서브 클래스 모두 동일한 메소드 서명에 대한 항목이 테이블에있는 경우, 서브 클래스의 버전이 먼저 발견되고 수퍼 클래스의 버전은 사용되지 않습니다. 이것은 "재정의"입니다.

이제 객체 인스턴스를 건너 뛰고 서브 클래스로 시작한다고 가정합니다. 해결 방법은 위와 같이 진행되어 일종의 "재정의 가능한"정적 메서드를 제공 할 수 있습니다. 그러나 컴파일러는 클래스에 대해 지정되지 않은 유형의 개체를 쿼리하기 위해 런타임까지 기다리지 않고 알려진 클래스에서 시작하므로 컴파일 타임에 해결이 모두 발생할 수 있습니다. 원하는 버전을 포함하는 클래스를 항상 지정할 수 있으므로 정적 메서드를 "무시"할 필요가 없습니다.


생성자 "인터페이스"

다음은 질문에 대한 최근 수정 사항을 다루는 좀 더 많은 자료입니다.

IXMLizable 각 구현에 대해 생성자와 같은 메서드를 효과적으로 위임하려는 것 같습니다. 잠시 동안 인터페이스로이를 시행하는 것은 잊어 버리고이 요구 사항을 충족하는 클래스가 있다고 가정하십시오. 어떻게 사용 하시겠습니까?

class Foo implements IXMLizable<Foo> {
  public static Foo newInstanceFromXML(Element e) { ... }
}

Foo obj = Foo.newInstanceFromXML(e);

Foo 이름을 명시 적으로 지정해야하므로 컴파일러는 실제로 필요한 팩토리 메소드가 있는지 확인할 수 있습니다. 그렇지 않은 경우 어떻게합니까? 내가 구현할 수있는 경우 IXMLizable 은 "생성자"를 결여, 그리고 인스턴스를 생성하고 코드에 전달, 그것은이다 IXMLizable 필요한 모든 인터페이스.

구성은 인터페이스가 아니라 구현의 일부입니다. 인터페이스에서 성공적으로 작동하는 코드는 생성자에 대해 신경 쓰지 않습니다. 생성자를 신경 쓰는 코드는 어쨌든 구체적인 유형을 알아야하며 인터페이스는 무시할 수 있습니다.

출처 : https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface
728x90
반응형