문제

이 기사를 읽었습니다. 여기 바인딩 된 유형으로 작동하는 방법. 내가 얻으려고하는 것은 네 가지 사례를 처리하는 매개 변수화 된 방법입니다.

  • t는 B만을 확장
  • t가 B와 i (여기서 d)
  • t는 i 만
  • 를 확장합니다.
  • 모든 것

여기서 코드가 있습니다.

public class Main {

    public static void main(String... args) {
        B b = new B();
        D d = new D();
        I i = new I() {
        };
        handle("aaasd");
        handle(b);
        handle(d); <---- Problem 1
        handle(i);
    }

    public static class B {

    }

    public static interface I {

    }

    public static class D extends B implements I {

    }


    public static <T> void handle(T objT) {
        System.out.println("T");
    }

    private static <T extends B> void handle(T obj) {
        System.out.println("B");
    }

    public static <T extends B & I> void handle(T objT) { <--- Problem 2
        System.out.println("B+I");
    }

    private static <T extends I> void handle(T obj) {
        System.out.println("I");
    }
}
.

컴파일러는 두 가지를 불평하고 다음과 같이 말합니다.

  1. 모호한 호출

    메서드 핸들 (main.d)은 유형의 메인에 모호합니다. 나는 문제가 문제 번호 2와 같은 원인으로 인해 발생하는 것 같아 & 나는 분명히 T의 유형을 b의 아형에 명확하게 경계시켜 내 의견으로 모호성을 제거합니다.

  2. 동일한 소거 핸들

    방법 핸들 (t)은 유형의 다른 방법으로 동일한 지우개 핸들 (main.b)을 갖는다. 내 추측은 이것이 모든 문제의 실제 원인이라는 것입니다. 자바는 어떻게 든 런타임 중에 내가 경계를 제거합니까? 그러나 B 유형으로 메소드를 호출하면 agoted 메소드를 호출하지 않습니다.

  3. 누군가가 B, B & I 및 I을 구별하는 방법을 설명 할 수 있습니까?

도움이 되었습니까?

해결책

Java의 모든 제네릭에 적용되는 유형 삭제라는 개념이 있습니다.일반 메소드를 사용하여 편집 후 바이트 코드의 메소드가 삭제로 나타납니다. 그래서

public static <T> void handle(T objT) {
    System.out.println("T");
}

private static <T extends B> void handle(T obj) {
    System.out.println("B");
}

public static <T extends B & I> void handle(T objT) { <--- Problem 2
    System.out.println("B+I");
}

private static <T extends I> void handle(T obj) {
    System.out.println("I");
}
.

실제로

가됩니다
public static void handle(Object objT) {
    System.out.println("T");
}

private static void handle(B obj) {
    System.out.println("B");
}

public static void handle(B objT) { 
    System.out.println("B+I");
}

private static void handle(I obj) {
    System.out.println("I");
}
.

타입 변수의 왼쪽 가장 왼쪽은 해당 유형의 매개 변수가 바뀌는 것입니다.볼 수 있듯이 두 번째 및 3 번째 방법 모두 동일한 이름과 동일한 매개 변수 유형이 동일합니다.같은 서명.컴파일러가 허용 할 수 없습니다.

그러나 경계의 구문은 인터페이스 유형이므로 모든 인터페이스 유형 이전에 클래스 유형을 제공하도록 강제합니다.

<T extends I & B>
.

가 작동하지 않습니다.또한 4 번째 방법이 다시 동일한 지우개가 있기 때문에 작동하지 않습니다.

추가로 호출

handle(d);
.

는 제 2 및 4 번째 방법이 처리 할 수 있기 때문에 문제가 있지만, 아무도 더 구체적으로 존재하지 않습니다.이것은 과부하 모호함으로 알려져 있습니다.

다른 팁

Java는 런타임 중에 I로 경계를 제거합니까?

아니오, Java는 런타임 (반영 목적을 제외하고) 유형 정보를 런타임에 모든 유형 정보를 제거합니다.

경계를 사용하여 컴파일러는 코드를 handle(Object), handle(B)handle(I)T extends B & I에 대한 코드를 변환 할 수 있지만 컴파일러가 충돌을 가져올 수 있습니다.

afaik, 공통된 바운드를 가지지 않고이 문제를 해결할 수있는 방법은 없습니다.T extends D 대신 T extends B & I 대신 D extends B implements I 또는 메소드 이름을 변경하거나 다른 매개 변수를 추가 할 수 있습니다.

다른 방법은 B + I 케이스에 B + i 케이스에 로직을 추가하고 내부의 두 번째 조건을 확인하는 것일 수 있습니다.

private static <T extends B> void handle(T obj) {
    if( obj instanceof I) { 
      System.out.println("B+I");
    }
    else {
      System.out.println("B");
    }
}
.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top