programing

Java 인터페이스에서 정적 메서드를 정의할 수 없는 이유는 무엇입니까?

javaba 2023. 1. 9. 21:26
반응형

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의 파트 H에서 자세한 내용을 볼 수 있습니다.

정적 메서드 재정의

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

정적 메서드는 컴파일 시 해결할 수 있습니다.동적 디스패치는 컴파일러가 객체의 구체적인 유형을 결정할 수 없기 때문에 호출할 메서드를 해결할 수 없는 인스턴스 메서드에 적합합니다.단, 스태틱 메서드를 호출하려면 클래스가 필요합니다.또, 그 클래스는 컴파일시에 스태틱하게 인식되기 때문에, 다이나믹 디스패치는 불필요합니다.

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

각 클래스에 메서드 시그니처(이름 및 파라미터 유형)를 실제 코드 청크에 매핑하여 메서드를 구현하는 해시 테이블이 있다고 가정합니다.가상 시스템은 인스턴스에서 메서드를 호출하려고 하면 해당 클래스에 대한 개체를 쿼리하고 클래스 테이블에서 요청된 서명을 검색합니다.메서드 본문이 발견되면 호출됩니다.그렇지 않으면 클래스의 부모 클래스를 가져오고 거기에서 조회가 반복됩니다.은 메서드가가 없어질 그, 「」가 .NoSuchMethodError.

슈퍼클래스와 서브클래스의 테이블에 모두 같은 메서드시그니처의 엔트리가 있는 경우 서브클래스의 버전이 먼저 표시되며 슈퍼클래스의 버전은 사용되지 않습니다.이는 "오버라이드"입니다.

이제 개체 인스턴스를 건너뛰고 하위 클래스로 시작합니다.해결은 위와 같이 진행되어 일종의 "덮어쓸 수 있는" 정적 메서드를 제공할 수 있습니다.그러나 컴파일러가 클래스에 대해 지정되지 않은 유형의 개체를 쿼리하기 위해 런타임까지 기다리는 것이 아니라 알려진 클래스에서 시작하므로 모든 해결이 컴파일 시간에 발생할 수 있습니다.원하는 버전을 포함하는 클래스를 언제든지 지정할 수 있으므로 정적 메서드를 "덮어쓰기"하는 것은 의미가 없습니다.


컨스트럭터 "인터페이스"

최근 편집한 질문에 대한 내용을 좀 더 알려드리겠습니다.

「컨스트럭터」의 각 , 「와 같은 것.IXMLizable인터페이스로 이것을 강제하려고 하는 것은 잠시 잊고, 이 요건을 만족시키는 클래스가 몇 개 있다고 가정해 주세요.떻게게? 츠요시

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

Foo obj = Foo.newInstanceFromXML(e);

인 타입의 이름을 으로 붙여야 Foo컴파일러는 새로운 오브젝트를 "삭제"할 때 그것이 실제로 필요한 공장 출하 방법을 가지고 있는지 확인할 수 있습니다.안안되????이 기능을 구현할 수 있다면IXMLizable'컨스트럭터'가 결여되어 있는 경우, 인스턴스를 생성하여 당신의 코드에 전달하면, 그것은IXMLizable필요한 인터페이스를 모두 갖추고 있습니다.

구축은 인터페이스가 아니라 구현의 일부입니다.인터페이스에서 정상적으로 동작하는 코드는 컨스트럭터에는 관심이 없습니다.컨스트럭터와 관련된 코드는 구체적인 유형을 알아야 하며 인터페이스는 무시해도 됩니다.

이것은 이미 묻고 대답한 것입니다.여기서

내 답변을 복제하려면:

인터페이스에 스태틱 방식을 선언하는 것은 의미가 없습니다.통상의 콜 MyInterface.staticMethod()에서는 실행할 수 없습니다.구현 클래스 MyImplementor.staticMethod()를 지정하여 호출하는 경우 실제 클래스를 알아야 합니다.따라서 인터페이스가 클래스를 포함하든 포함하지 않든 상관없습니다.

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

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

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

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

이는 "Java가 그렇게 하기 때문"이라고 말할 수 있지만, 실제로는 다른 설계 결정의 논리적인 결과이며, 또한 매우 타당한 이유가 있습니다.

Java 8의 등장으로 인터페이스에 디폴트 메서드와 스태틱 메서드를 쓸 수 있게 되었습니다.docs.oracle/static Method

예를 들어 다음과 같습니다.

public interface Arithmetic {

    public int add(int a, int b);

    public static int multiply(int a, int b) {
        return a * b;
    }
}
public class ArithmaticImplementation implements Arithmetic {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) {
        int result = Arithmetic.multiply(2, 3);
        System.out.println(result);
    }
}

결과: 6

힌트: 스태틱인터페이스 메서드를 호출하는 경우, 어느 클래스에서도 실장할 필요는 없습니다.이것은 슈퍼클래스의 스태틱메서드에 대해 같은 규칙이 인터페이스의 스태틱메서드에 적용되기 때문에 발생합니다.

통상, 이것은 공장 패턴을 사용해 행해집니다.

public interface IXMLizableFactory<T extends IXMLizable> {
  public T newInstanceFromXML(Element e);
}

public interface IXMLizable {
  public Element toXMLElement();
}

정적 메서드는 하위 클래스에서 재정의할 수 없으므로 추상화할 수 없습니다.인터페이스의 모든 메서드는 사실 추상적입니다.

Java 인터페이스에서 정적 메서드를 정의할 수 없는 이유는 무엇입니까?

사실 Java 8에서는 가능합니다.

Java 문서에 따르면:

정적 메서드는 객체가 아닌 정의된 클래스와 관련된 메서드입니다.클래스의 모든 인스턴스가 정적 메서드를 공유합니다.

Java 8에서는 인터페이스에 디폴트 메서드와 스태틱메서드설정할 수 있습니다.이를 통해 라이브러리에서 도우미 메서드를 쉽게 구성할 수 있습니다.인터페이스에 고유한 스태틱메서드를 다른 클래스가 아닌 같은 인터페이스로 유지할 수 있습니다.

기본 방식의 예:

list.sort(ordering);

대신

Collections.sort(list, ordering);

스태틱 메서드의 예(doc 자체에서):

public interface TimeClient {
    // ...
    static public ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +
                "; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

    default public ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }    
}

인터페이스는 클래스가 아닌 오브젝트인스턴스와 본질적으로 관련되어 있는 다형성에 관련되어 있습니다.따라서 스태틱은 인터페이스의 컨텍스트에서는 의미가 없습니다.

첫째, 모든 언어 결정은 언어 창작자에 의해 내려진 결정이다.소프트웨어 엔지니어링, 언어 정의, 컴파일러/인터프리터 작성에는 정적 메서드가 인터페이스의 일부가 될 수 없다는 것은 없습니다.몇 가지 언어를 만들고 컴파일러를 작성했습니다.모두 앉아서 의미 있는 의미를 정의하는 것입니다.컴파일러가 런타임에 메서드의 해결을 연기해야 하는 경우에도 인터페이스의 정적 메서드의 의미는 매우 명확하다고 생각합니다.

둘째, 스태틱 방식을 사용한다는 것은 스태틱 방식을 포함하는 인터페이스 패턴을 갖는 타당한 이유가 있다는 것을 의미합니다.여러분들을 대변할 수는 없지만 저는 정기적으로 스태틱 방식을 사용합니다.

가장 가능성이 높은 정답은 언어가 정의되었을 때 인터페이스의 정적 메서드에 대한 필요성은 인식되지 않았다는 것입니다.Java는 몇 년 동안 크게 성장했고, 이것은 분명히 관심을 얻은 아이템이다.Java 7에 대해 살펴본 것은 언어 변경으로 이어질 수 있는 관심 수준까지 올라갔음을 나타냅니다.예를 들어 서브클래스 인스턴스의 스태틱 변수에 액세스하기 위해 non-static getter 메서드를 호출할 수 있도록 오브젝트를 인스턴스화할 필요가 없어졌을 때 행복합니다.

  • 정적 메서드를 재정의할 수 없는 특별한 이유가 있습니까?

그 질문에 대한 정의를 다시 쓰도록 하겠습니다.

  • 컴파일 시 해결된 메서드가 런타임에 해결되지 않는 특별한 이유가 있습니까?

또는 인스턴스 없이 메서드를 호출하고 싶지만 클래스를 알고 있는 경우 없는 인스턴스를 기반으로 해결하려면 어떻게 해야 합니까?

정적 메서드는 인스턴스 메서드와 같은 가상 메서드가 아니기 때문에 Java 설계자는 인터페이스에 사용하지 않기로 결정한 것 같습니다.

단, 스태틱메서드를 포함한 클래스를 인터페이스 내부에 배치할 수 있습니다.시도해 볼 수 있어요!

public interface Test {
    static class Inner {
        public static Object get() {
            return 0;
        }
    }
}

★★EDIT: As of Java 8, static methods are now allowed in interfaces.

Java 8이 인터페이스에서 허용되기 때문에 정적 메서드는 맞지만, 당신의 예는 여전히 작동하지 않습니다.스태틱 메서드를 정의만 할 수는 없습니다.실장하지 않으면 컴파일 오류가 발생합니다.

여러 답변에서 재정의 가능한 정적 메서드의 개념에 대한 문제를 논의했습니다.그러나 때때로 사용하고 싶은 것이 바로 그것인 것처럼 보이는 패턴을 발견할 수 있습니다.

예를 들어, 값 개체가 있지만 값 개체를 조작하는 명령도 있는 개체 관계 계층에 대해 작업합니다.다양한 이유로 각 값 오브젝트클래스는 프레임워크가 명령어인스턴스를 검출할 수 있는 스태틱메서드를 정의해야 합니다.예를 들어, 수행할 사용자를 작성하려면:

cmd = createCmd(Person.getCreateCmdId());
Person p = cmd.execute();

ID로 사람을 로드하려면

cmd = createCmd(Person.getGetCmdId());
cmd.set(ID, id);
Person p = cmd.execute();

이것은 매우 편리하지만 문제가 있습니다.특히 스태틱메서드의 존재는 인터페이스에 강제할 수 없습니다.인터페이스 내에서 덮어쓸 수 있는 정적 방식이 우리가 필요로 하는 바로 그것입니다. 만약 그것이 어떻게든 작동한다면 말이죠.

EJB는 홈 인터페이스를 통해 이 문제를 해결합니다. 각 개체는 홈을 찾는 방법을 알고 홈에는 "정적" 메서드가 포함되어 있습니다.이렇게 하면 필요에 따라 "static" 메서드를 덮어쓸 수 있습니다.또, 통상의 인터페이스(「리모트」라고 불립니다)를, 빈의 인스턴스에 적용되지 않는 메서드로 복잡하게 하지 않아도 됩니다.일반 인터페이스에서 "get Home()" 메서드를 지정하도록 합니다.Home 객체의 인스턴스(싱글톤일 수 있음)를 반환하면 발신자는 모든 Person 객체에 영향을 주는 작업을 수행할 수 있습니다.

범용성이 없으면 스태틱인터페이스는 쓸모가 없습니다.모든 스태틱메서드 콜은 컴파일 시에 해결되기 때문입니다.그래서 그들은 실제로 쓸모가 없다.

제네릭에서는 기본 구현 여부에 관계없이 사용할 수 있습니다.분명히 덮어쓰기 등이 있을 필요가 있을 것이다.다만, 그러한 사용법은 (다른 답변이 둔감하게 지적하고 있듯이) 그다지 OO적이지 않았기 때문에, 유용하게 실장하기 위해서 필요한 노력을 할 가치가 없다고 생각된다.

Why can't I define a static method in a Java interface?

인터페이스의 모든 메서드는 명시적으로 추상화되므로 정적 메서드는 추상화할 수 없으므로 스태틱으로 정의할 수 없습니다.

할 수 를 들어, 「」는 참조할 수 없습니다.ISomething.member인터페이스는 항상 인터페이스의 서브클래스의 인스턴스를 참조하는 변수를 통해 참조됩니다.따라서 인터페이스 참조는 서브클래스의 인스턴스가 없으면 어떤 서브클래스를 참조하는지 알 수 없습니다.

따라서 인터페이스의 정적 메서드에 가장 가까운 근사치는 "this"를 무시하는 비정적 메서드입니다.즉, 인스턴스의 비정적 멤버에 액세스하지 않습니다.저수준 추상화에서는 모든 비정적 메서드(vtable 검색 후)는 실제로는 클래스 범위를 가진 함수로, "this"를 암묵적인 형식 매개 변수로 받아들입니다.Scala의 싱글톤 객체와 Java와의 상호 운용성을 그 개념의 증거로 볼 수 있습니다.따라서 모든 스태틱메서드는 클래스 스코프를 가진 함수로 "this" 파라미터를 사용하지 않습니다.따라서 일반적으로 스태틱 메서드는 스태틱하게 호출할 수 있지만 앞서 설명한 바와 같이 인터페이스에는 구현이 없습니다(추상적입니다).

따라서 인터페이스의 스태틱 방식에 가장 가까운 근사치를 얻으려면 비 스태틱 방식을 사용하여 비 스태틱인스턴스 멤버에 접근하지 마십시오.(시)를으로 링크하는 없기 .ISomething.member()인터페이스의 정적 메서드의 유일한 장점은 암묵적인 "this"를 입력(즉, 무시)하지 않기 때문에 비정적 인스턴스 멤버에 대한 접근을 허용하지 않는다는 것입니다.이는 "this"에 액세스하지 않는 함수가 불변하며 포함된 클래스에 대해 읽기 전용이 아님을 암시적으로 선언합니다., 에서의 "static", "static"ISomething, 에게, 접속을 시도하고 있는 것 같습니다.ISomething.member()컴파일러 에러의 원인이 됩니다.컴파일러 오류가 충분히 설명되었더라면, 그들이 원하는 것을 성취하기 위해 비정적 방법을 사용하여 사람들을 교육하는 것보다 더 좋을 것 같다.이 사이트에 있는 시간이므로, 많은 사람들에게 직관적이지 않은 문제입니다.컴파일러 오류가 충분히 설명되었더라면, 그들이 원하는 것을 성취하기 위해 비정적 방법을 사용하여 사람들을 교육하는 것보다 더 좋을 것 같다.이 사이트에 있는 시간이므로, 많은 사람들에게 직관적이지 않은 문제입니다.정확한 이해를 위해 잠시 생각을 해야 했다.

인터페이스에서 가변 스태틱필드를 취득하려면 인터페이스에서 비 스태틱게터 메서드와 세터 메서드를 사용하여 서브클래스의 스태틱필드에 액세스합니다.Sidenote와의 에서 불변의 할 수 .static final.

인터페이스는 클래스가 제공하는 항목의 목록만 제공할 뿐 실제 구현은 제공하지 않습니다. 이것이 바로 스태틱 항목입니다.

통계 정보를 원할 경우 추상 클래스를 사용하여 상속합니다. 그렇지 않을 경우 정적을 제거하십시오.

도움이 됐으면 좋겠네요!

스태틱 메서드는 클래스의 인스턴스가 아닌 클래스에 속하고 인터페이스는 클래스가 아니기 때문에 인터페이스에 스태틱메서드를 정의할 수 없습니다.자세한 것은 이쪽.

그러나 필요한 경우 다음을 수행할 수 있습니다.

public class A {
  public static void methodX() {
  }
}

public class B extends A {
  public static void methodX() {
  }
}

이 경우 methodX()라고 불리는2개의 다른 스태틱메서드를 가진 2개의 클래스가 있습니다.

이를 수행할 수 있다고 가정합니다.다음 예를 검토해 주십시오.

interface Iface {
  public static void thisIsTheMethod();
}

class A implements Iface {

  public static void thisIsTheMethod(){
    system.out.print("I'm class A");
  }

}

class B extends Class A {

  public static void thisIsTheMethod(){
    System.out.print("I'm class B");
  } 
}

SomeClass {

  void doStuff(Iface face) {
    IFace.thisIsTheMethod();
    // now what would/could/should happen here.
  }

}

실장할 수 있는 것은 스태틱인터페이스입니다(인터페이스의 스태틱 방식이 아닌).특정 스태틱인터페이스를 실장하는 모든 클래스는 대응하는 스태틱메서드를 실장해야 합니다.어떤 클래스 클래즈에서도 스태틱인터페이스 SI 를 취득할 수 있습니다.

SI si = clazz.getStatic(SI.class); // null if clazz doesn't implement SI
// alternatively if the class is known at compile time
SI si = Someclass.static.SI; // either compiler errror or not null

됩니다.si.method(params)컴파일 타임 미지의 클래스에서 SI 스태틱메서드의 실장을 취득(또는 실장 체크)할 수 있기 때문에, 이것은 편리합니다.다이나믹 디스패치는 필요하며, 클래스의 스태틱메서드(최종적이지 않은 경우)를 확장함으로써(스태틱인터페이스를 통해 호출했을 경우) 클래스의 스태틱메서드를 덮어쓸 수 있습니다.이러한 메서드는 클래스의 정적 변수에만 액세스할 수 있습니다.

Java 8이 이 문제를 해결한다는 것을 알고 있지만, 현재 작업 중인 시나리오(Java 7을 사용하여 잠김)와 연계하여 인터페이스에서 정적 메서드를 지정할 수 있다면 도움이 될 것이라고 생각했습니다.

여러 가지 이유로 값을 평가하는 도우미 메서드와 함께 "id" 및 "displayName" 필드를 정의한 열거형 정의가 있습니다.인터페이스를 실장하는 것으로, getter 메서드가 갖추어져 있는 것을 확인할 수 있습니다만, 스태틱도우미 메서드는 사용할 수 없습니다.열거형이기 때문에 도우미 메서드를 상속된 추상 클래스 또는 이와 유사한 클래스로 오프로드할 수 있는 깔끔한 방법이 없기 때문에 메서드는 열거형 자체에 정의해야 합니다.또한 열거형이기 때문에 실제로 instance 개체로 전달하여 인터페이스 유형으로 취급할 수 없지만 인터페이스를 통해 스태틱 도우미 메서드의 존재를 요구할 수 있다는 점이 Java 8에서 지원되는 것이 좋습니다.

여기 제 요점을 설명하는 코드가 있습니다.

인터페이스 정의:

public interface IGenericEnum <T extends Enum<T>> {
    String getId();
    String getDisplayName();
    //If I was using Java 8 static helper methods would go here
}

하나의 열거형 정의의 예:

public enum ExecutionModeType implements IGenericEnum<ExecutionModeType> {
    STANDARD ("Standard", "Standard Mode"),
    DEBUG ("Debug", "Debug Mode");

    String id;
    String displayName;

    //Getter methods
    public String getId() {
        return id;
    }

    public String getDisplayName() {
        return displayName;
    }

    //Constructor
    private ExecutionModeType(String id, String displayName) {
        this.id = id;
        this.displayName = displayName;
    }

    //Helper methods - not enforced by Interface
    public static boolean isValidId(String id) {
        return GenericEnumUtility.isValidId(ExecutionModeType.class, id);
    }

    public static String printIdOptions(String delimiter){
        return GenericEnumUtility.printIdOptions(ExecutionModeType.class, delimiter);
    }

    public static String[] getIdArray(){
        return GenericEnumUtility.getIdArray(ExecutionModeType.class);
    }

    public static ExecutionModeType getById(String id) throws NoSuchObjectException {
        return GenericEnumUtility.getById(ExecutionModeType.class, id);
    }
}

일반 열거 유틸리티 정의:

public class GenericEnumUtility {
    public static <T extends Enum<T> & IGenericEnum<T>> boolean isValidId(Class<T> enumType, String id) {       
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(enumOption.getId().equals(id)) {
                return true;
            }
        }

        return false;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String printIdOptions(Class<T> enumType, String delimiter){
        String ret = "";
        delimiter = delimiter == null ? " " : delimiter;

        int i = 0;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(i == 0) {
                ret = enumOption.getId();
            } else {
                ret += delimiter + enumOption.getId();
            }           
            i++;
        }

        return ret;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String[] getIdArray(Class<T> enumType){
        List<String> idValues = new ArrayList<String>();

        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            idValues.add(enumOption.getId());
        }

        return idValues.toArray(new String[idValues.size()]);
    }

    @SuppressWarnings("unchecked")
    public static <T extends Enum<T> & IGenericEnum<T>> T getById(Class<T> enumType, String id) throws NoSuchObjectException {
        id = id == null ? "" : id;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(id.equals(enumOption.getId())) {
                return (T)enumOption;
            }
        }

        throw new NoSuchObjectException(String.format("ERROR: \"%s\" is not a valid ID. Valid IDs are: %s.", id, printIdOptions(enumType, " , ")));
    }
}

인터페이스에서 정적 메서드가 허용된다고 가정합니다.* 이 메서드는 구현된 모든 클래스에서 강제로 해당 메서드를 선언합니다.* 인터페이스는 보통 오브젝트를 통해 사용되기 때문에 효과적인 방법은 비정적 방법뿐입니다.* 특정 인터페이스를 알고 있는 클래스는 해당 정적 메서드를 호출할 수 있습니다.따라서 구현 클래스의 정적 메서드는 아래에서 호출되지만 호출자 클래스는 어떤 메서드를 인식할 수 없습니다.그걸 어떻게 알아?그것을 추측할 수 있는 인스턴스화는 없다!

인터페이스는 오브젝트를 조작할 때 사용되는 것으로 생각되었습니다.이렇게 하면 객체가 특정 클래스에서 인스턴스화되므로 이 마지막 문제가 해결됩니다.호출 클래스는 인스턴스화가 세 번째 클래스에 의해 수행될 수 있기 때문에 어떤 클래스가 특정 클래스인지 알 필요가 없습니다.따라서 호출 클래스는 인터페이스만 인식합니다.

이를 스태틱 메서드로 확장하려면 구현 클래스를 미리 지정한 후 호출 클래스에 참조를 전달할 수 있어야 합니다.이 경우 인터페이스의 스태틱메서드를 통해 클래스를 사용할 수 있습니다.하지만 이 참조와 객체의 차이점은 무엇일까요?우리는 단지 그것이 수업이었음을 나타내는 물체가 필요합니다.오브젝트는 오래된 클래스를 나타내며 오래된 스태틱메서드를 포함한 새로운 인터페이스를 구현할 수 있습니다.이러한 메서드는 현재 비 스태틱입니다.

메타클래스는 이런 용도로 사용됩니다.Java Class of Java 를 사용해 볼 수 있습니다.그러나 문제는 Java가 이를 위해 충분히 유연하지 않다는 것입니다.인터페이스의 클래스 오브젝트에 메서드를 선언할 수 없습니다.

이것은 메타적인 문제 - 필요한 경우

..블랙블랙

어쨌든 간단한 회피책이 있습니다.즉, 같은 논리로 비정적 방법을 만들 수 있습니다.그 후 메서드를 호출할 개체를 먼저 만들어야 합니다.

이 문제를 해결하려면: 오류: 메서드 본문이 없거나 추상 정적 보이드 메인(String[] args)을 선언합니다.

interface I
{
    int x=20;
    void getValue();
    static void main(String[] args){};//Put curly braces 
}
class InterDemo implements I
{
    public void getValue()
    {
    System.out.println(x);
    }
    public static void main(String[] args)
    {
    InterDemo i=new InterDemo();
    i.getValue();   
    }

}

출력: 20

이제 인터페이스에서 스태틱 방식을 사용할 수 있습니다.

java는 스태틱인터페이스 메서드가 필요없기 때문에 없다고 생각합니다.그렇게 생각하실지 모르겠지만...어떻게 사용하시겠습니까?만약 네가 그들을 이렇게 부르고 싶다면

MyImplClass.myMethod()

인터페이스로 선언할 필요가 없습니다.만약 네가 그들을 이렇게 부르고 싶다면

myInstance.myMethod()

정적이면 안 됩니다.실제로 첫 번째 방법을 사용하지만 각 구현에 이러한 스태틱 방식을 적용하려는 경우 인터페이스와 발신 코드 간의 계약이 아니라 실제로는 코딩 규약입니다.

인터페이스를 사용하면, 인터페이스를 실장하는 클래스의 인스턴스와 발신 코드간의 계약을 정의할 수 있습니다.또한 Java는 이 계약이 위반되지 않았음을 확인할 수 있도록 지원하므로 어떤 계층이 이 계약을 이행하는지 걱정할 필요 없이 "계약에 서명한 사람"만 있으면 됩니다.스태틱 인터페이스의 경우 코드

MyImplClass.myMethod()

는, 각 인터페이스의 실장 마다 이 방식을 채용하고 있는 것에 의존하지 않기 때문에, 확실히 하기 위해서 Java 가 필요한 것은 아닙니다.

인터페이스에 스태틱 메서드가 필요한 것은 기본적으로 스태틱 메서드는 오브젝트 전체의 instance를 작성할 필요가 없을 때 사용됩니다.인터페이스의 전체 아이디어는 OOP 개념을 도입하고 개념에서 전환하는 스태틱 메서드를 도입하는 것입니다.

언급URL : https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface

반응형