[java] ‘E’, ‘T’및 ”의 차이점은 무엇입니까? Java 제네릭의 경우

다음과 같은 Java 코드를 발견했습니다.

public interface Foo<E> {}

public interface Bar<T> {}

public interface Zar<?> {}

위의 세 가지 차이점은 무엇이며 Java에서 이러한 유형의 클래스 또는 인터페이스 선언이라고하는 것은 무엇입니까?



답변

첫 두 개 사이에는 차이가 없습니다. 형식 매개 변수 ( E또는 T)에 다른 이름을 사용하고 있습니다.

세 번째는 유효한 선언하지 않습니다 – ?A와 사용되는 와일드 카드 타입 제공 할 때 사용되는 인수를 , 예를 들어 List<?> foo = ...그 방법을 foo몇 가지 유형의 목록을 의미하지만, 우리는 무엇을 알고하지 않습니다.

이 모든 것이 제네릭 이며 꽤 큰 주제입니다. 물론 더 많은 자료가 있지만 다음 자료를 통해 그것에 대해 배우고 싶을 수도 있습니다.


답변

다른 것보다 더 많은 관습입니다.

  • T 유형이 될 것입니다
  • E요소 (요소 List<E>의 목록)
  • K키 ( Map<K,V>)
  • V 값 (반환 값 또는 맵핑 된 값)

그것들은 완전히 상호 교환 가능합니다 (같은 선언에도 불구하고 충돌합니다).


답변

이전 답변에서는 유형 매개 변수 (T, E 등)에 대해 설명했지만 와일드 카드, “?”또는 이들 사이의 차이점에 대해서는 설명하지 않으므로 이에 대해 설명하겠습니다.

먼저, 명확하게 말하면 와일드 카드와 유형 매개 변수는 동일하지 않습니다. 유형 매개 변수가 범위의 유형을 나타내는 일종의 변수 (예 : T)를 정의하는 경우 와일드 카드는 그렇지 않습니다. 와일드 카드는 일반 유형에 사용할 수있는 허용 가능한 유형 세트 만 정의합니다. 경계없이 (extends 또는 super)가 와일드 카드는 “여기에 모든 유형 사용”을 의미합니다.

와일드 카드는 항상 꺾쇠 괄호 사이에 있으며 일반 유형의 컨텍스트에서만 의미가 있습니다.

public void foo(List<?> listOfAnyType) {...}  // pass a List of any type

public <?> ? bar(? someType) {...}  // error. Must use type params here

또는

public class MyGeneric ? {      // error
    public ? getFoo() { ... }   // error
    ...
}

겹치는 부분이 더 혼란스러워집니다. 예를 들면 다음과 같습니다.

List<T> fooList;  // A list which will be of type T, when T is chosen.
                  // Requires T was defined above in this scope
List<?> barList;  // A list of some type, decided elsewhere. You can do
                  // this anywhere, no T required.

메소드 정의에서 가능한 것과 겹치는 부분이 많이 있습니다. 다음은 기능적으로 동일합니다.

public <T> void foo(List<T> listOfT) {...}
public void bar(List<?> listOfSomething)  {...}

겹치는 부분이 있다면 왜 다른 것을 사용합니까? 때로는 정직한 스타일 일 수도 있습니다. 어떤 사람들은 타입 매개 변수 가 필요 하지 않으면 코드를 더 단순하고 읽기 쉽게하기 위해 와일드 카드를 사용해야 한다고 말합니다 . 위에서 설명한 한 가지 주요 차이점 : 형식 매개 변수는 범위의 다른 곳에서 사용할 수있는 형식 변수 (예 : T)를 정의합니다. 와일드 카드는 그렇지 않습니다. 그렇지 않으면, 유형 매개 변수와 와일드 카드 사이에는 두 가지 큰 차이점이 있습니다.

형식 매개 변수는 여러 바인딩 클래스를 가질 수 있습니다. 와일드 카드는 다음을 수행 할 수 없습니다.

public class Foo <T extends Comparable<T> & Cloneable> {...}

와일드 카드는 하한을 가질 수 있습니다. 유형 매개 변수는 다음을 수행 할 수 없습니다.

public void bar(List<? super Integer> list) {...}

위의 List<? super Integer>정의 Integer는 와일드 카드에서 하한으로 정의 됩니다. 즉, List 유형은 Integer 또는 Super-Integer 유형이어야합니다. 제네릭 형식 경계는 자세히 다루고 싶지 않습니다. 즉, 어떤 유형 을 정의 할 수 있습니다 일반 유형이 될 수 할 수 있습니다. 이를 통해 제네릭을 다형성으로 처리 할 수 ​​있습니다. 예 :

public void foo(List<? extends Number> numbers) {...}

당신은을 전달할 수 있습니다 List<Integer>, List<Float>,List<Byte> , 등numbers . 유형 경계가 없으면 작동하지 않습니다. 즉, 제네릭의 방식입니다.

마지막으로 와일드 카드를 사용하여 다른 방법으로는 할 수없는 일을하는 메소드 정의가 있습니다.

public static <T extends Number> void adder(T elem, List<? super Number> numberSuper) {
    numberSuper.add(elem);
}

numberSuper번호의 목록 또는 번호 (예를 들어, 어떤 슈퍼 될 수 있습니다 List<Object>), 그리고 elem번호 또는 하위 유형이어야합니다. 모든 경계에서 컴파일러는 형식 .add()이 안전한지 확인할 수 있습니다 .


답변

유형 변수 <T>는 사용자가 지정하는 기본이 아닌 유형 (예 : 모든 클래스 유형, 인터페이스 유형, 배열 유형 또는 다른 유형 변수) 일 수 있습니다.

가장 일반적으로 사용되는 유형 매개 변수 이름은 다음과 같습니다.

  • E-요소 (Java Collections Framework에서 광범위하게 사용)
  • K-키
  • N-숫자
  • T-유형
  • V-가치

Java 7에서는 다음과 같이 인스턴스화 할 수 있습니다.

Foo<String, Integer> foo = new Foo<>(); // Java 7
Foo<String, Integer> foo = new Foo<String, Integer>(); // Java 6


답변

가장 일반적으로 사용되는 유형 매개 변수 이름은 다음과 같습니다.

E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types

이 이름은 Java SE API 전체에서 사용됩니다.


답변

컴파일러는 다음과 같은 기능을 구성 할 때 각 와일드 카드 (예 : List의 물음표)를 캡처합니다 .

foo(List<?> list) {
    list.put(list.get()) // ERROR: capture and Object are not identical type.
}

그러나 V와 같은 일반적인 유형은 괜찮고 일반적인 방법으로 만듭니다 .

<V>void foo(List<V> list) {
    list.put(list.get())
}


답변