List, List <?>, List <T>, List <E> 및 List <Object>의 차이점 그렇지 않습니다 typesafe. 캐스팅이 나쁜 경우에만 런타임

의 차이점은 무엇입니까 List, List<?>, List<T>, List<E>, 그리고 List<Object>?

1. 목록

List:는 원시 유형이므로 그렇지 않습니다 typesafe. 캐스팅이 나쁜 경우에만 런타임 오류가 발생합니다. 캐스트가 나쁜 경우 컴파일 시간 오류가 필요합니다. 사용하지 않는 것이 좋습니다.

2. 목록 <?>

List<?>무제한 와일드 카드입니다. 그러나 그것이 무엇인지 잘 모르겠습니다. List<?>문제없이 인쇄 할 수 있습니다 .

public static void test(List<?> list){
    System.out.println(list);   // Works
}

에 항목을 추가 할 수없는 이유는 무엇 List<?>입니까?

public static void test(List<?> list){
    list.add(new Long(2));     // Error
    list.add("2");             // Error
    System.out.println(list);
}

3.리스트 <T>

public static void test(List<T> list){   // T cannot be resolved
    System.out.println(list);
}

이 구문을 이해하지 못합니다. 나는 이와 같은 것을 보았고 효과가있다.

public <T> T[] toArray(T[] a){
    return a;
}

때때로, 나는 참조 <T>하거나 <E>, 또는 <U>, <T,E>. 그들은 모두 같습니까 아니면 다른 것을 나타 냅니까?

4.리스트 <개체>

이 오류는 “이 방법 test(List<Object>)은 인수에 적용 할 수 없습니다 List<String>“입니다.

public static void test(List<Object> list){
    System.out.println(list);
}

나는 다음이를하려고하면 나는 “에서 캐스팅 할 수 없습니다 얻었다 List<String>List<Object>

test((List<Object>) names);

혼란 스러워요. String의 서브 클래스입니다 Object왜하지, List<String>의 서브 클래스 List<Object>?



답변

1) 수정

2) 항목 유형에 신경 쓰지 않는 “읽기 전용”목록으로 생각할 수 있습니다. 예를 들어 목록의 길이를 반환하는 메서드에서 사용할 수 있습니다.

3) T, E 및 U는 동일하지만 사람들은 유형에 T, 요소에 E, 값에 V, 키에 K를 사용하는 경향이 있습니다. 컴파일하는 메소드는 특정 유형의 배열을 가져 와서 동일한 유형의 배열을 반환한다고 말합니다.

4) 오렌지와 사과는 섞을 수 없습니다. 문자열 목록을 개체 목록이 필요한 메서드에 전달할 수 있다면 문자열 목록에 개체를 추가 할 수 있습니다. (그리고 모든 객체가 문자열은 아닙니다)


답변

마지막 부분 : String은 Object의 하위 집합이지만 List <String>은 List <Object>에서 상속되지 않습니다.


답변

이 표기법 List<?>은 “뭔가의 목록 (그러나 나는 무엇을 말하지 않습니까)”을 의미합니다. 코드 test는 목록에있는 모든 종류의 객체에서 작동하므로 공식적인 메소드 매개 변수로 작동합니다.

포인트 3과 같이 타입 파라미터를 사용하려면 타입 파라미터를 선언해야합니다. 이를위한 Java 구문 <T>은 함수 앞에 놓 입니다. 이것은 메소드 본문에서 이름을 사용하기 전에 공식 매개 변수 이름을 메소드에 선언하는 것과 정확히 유사합니다.

List<Object>받아들이지 않는 것에 관해서 는 List<String>, a String가 아니기 때문에 의미 가 있습니다 Object. 의 하위 클래스입니다 Object. 수정은 선언하는 것 public static void test(List<? extends Object> set) ...입니다. 그러나 extends Object모든 클래스는 직간접 적으로 확장되기 때문에 중복됩니다 Object.


답변

당신이 캐스팅 할 수없는 이유 List<String>에는 List<Object>당신이의 제약을 위반하는 것을 허용 할 것입니다 List<String>.

다음 시나리오를 생각해보십시오.가있는 경우 List<String>유형의 객체 만 포함해야합니다 String. ( final클래스 인)

이를에 캐스트 할 수 있으면 해당 목록 List<Object>에 추가 Object하여의 원래 계약을 위반할 수 List<String>있습니다.

따라서 일반적으로 클래스 C 클래스의 상속은 P, 당신이 말할 수 없다 GenericType<C>또한 상속 GenericType<P>.

NB 나는 이미 이전 답변에서 이것에 대해 언급했지만 그것을 확장하고 싶었습니다.


답변

자바 퍼즐을 읽는 것이 좋습니다. 선언의 상속, 제네릭, 추상화 및 와일드 카드에 대해 잘 설명합니다.
http://www.javapuzzlers.com/


답변

자바 역사의 맥락에서 그들에 대해 이야기하자;

  1. List:

목록은 모든 객체를 포함 할 수 있음을 의미합니다. 리스트는 Java 5.0 이전의 릴리스에있었습니다. Java 5.0은 이전 버전과의 호환성을 위해 List를 도입했습니다.

List list=new  ArrayList();
list.add(anyObject);
  1. List<?>:

?알 수없는 객체를 의미합니다. 와일드 카드 ?소개는 Generic Type으로 작성된 문제를 해결하기위한 것입니다. 와일드 카드 참조 ; 그러나 이것은 또 다른 문제를 일으킨다 :

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
  1. List< T> List< E>

프로젝트 Lib에 T 또는 E 유형이 없음을 전제로 일반 선언을 의미합니다.

  1. List< Object> 일반 매개 변수화를 의미합니다.

답변

세 번째 관점에서, “T”는 선언되지 않았기 때문에 해결할 수 없습니다. 일반적으로 일반 클래스를 선언 할 때 “T”를 바인딩 된 유형 매개 변수 의 이름으로 사용할 수 있습니다. 오라클의 자습서를 포함한 많은 온라인 예제 에서는 “T”를 예를 들어 type 매개 변수의 이름은 다음과 같은 클래스를 선언합니다.

public class FooHandler<T>
{
   public void operateOnFoo(T foo) { /*some foo handling code here*/}

}

당신이 것을 말하는 FooHandler's operateOnFoo방법을 염두에두고, 클래스 선언 자체에 선언 된 유형 “T”의 변수를 기대하고, 나중에 같은 다른 방법을 추가 할 수 있습니다

public void operateOnFoos(List<T> foos)

모든 경우에 T, E 또는 U에 유형 매개 변수의 모든 식별자가 있으며 구문을 사용하는 둘 이상의 유형 매개 변수를 가질 수도 있습니다.

public class MyClass<Atype,AnotherType> {}

네 번째 ponint에서 Sting은 Object의 하위 유형이지만 generics 클래스에는 그러한 관계 List<String>가 없으며 하위 유형이 아니며 List<Object>컴파일러 관점에서 두 가지 유형이 있습니다. 이 블로그 항목 에서 가장 잘 설명됩니다.