2009-03-25 2 views
1

Java에서 Generic 클래스의 인스턴스를 초기화 할 때 Statement의 양쪽에 Type을 지정하면 어떤 이점이 있습니까?Java에서 Generic 클래스의 인스턴스를 만드는 올바른 방법은 무엇입니까?

ArrayList<String> test = new ArrayList<String>(); 

과 :

ArrayList<String> test = new ArrayList<Object>(); 
:

ArrayList<String> test = new ArrayList(); 

(두 번째 문에 일치하지 않는 것 같다

아니면 다른 방법을 넣어,이 두 올바른 문장의 차이점은 무엇입니까

이 잘못된 세 번째 문과 일치하여 incompatible types 컴파일 오류가 발생합니다.)

답변

14

두 번째 명령문은 실행시 제네릭이 지워지므로 첫 번째 명령문과 다소 비슷합니다. "확인되지 않은 전환"경고가 표시됩니다. 그 이유는 내가 마음에 들지 않는 이유입니다. 이것은 구글 컬렉션이하는 일이다

List<String> test = newList(); 

을 다음

public static <T> List<T> newList() { 
    return new ArrayList<T>(); 
} 

과 :

더 좋은 방법은 다음과 같이 정적 일반적인 방법을하는 것입니다.

(그리고 당신은 거의 항상 ArrayList로하지, List로 목록을 선언해야한다 쉽게 나중에 구현을 전환 할 수 있습니다..)

편집 : 정확한 차이가 사이에 어떤 코멘트에 요청 dribeas을 두 선언, 그리고 왜 그들이 "다소간 동등한"것이라고 말했는지를 설명합니다. type erasure 때문에 이들 사이의 유일한 차이점은 경고입니다. 여기에 비교 코드의 작은 조각이다 :

import java.util.*; 

class GenericDeclarationTest { 
    public static void main(String[] args) { 
     List<String> list1 = new ArrayList<String>(); 
     list1.add(""); 
     String s1 = list1.get(0); 
     List<String> list2 = new ArrayList(); 
     list2.add(""); 
     String s2 = list2.get(0); 
    } 
} 

는 그리고 여기 (javap -c GenericDeclarationTest 인쇄로) 생성 된 바이트 코드입니다 :

Compiled from "GenericDeclarationTest.java" 
class GenericDeclarationTest extends java.lang.Object{ 
GenericDeclarationTest(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: new  #2; //class java/util/ArrayList 
    3: dup 
    4: invokespecial #3; //Method java/util/ArrayList."<init>":()V 
    7: astore_1 
    8: aload_1 
    9: ldc  #4; //String 
    11: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 
    16: pop 
    17: aload_1 
    18: iconst_0 
    19: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 
    24: checkcast  #7; //class java/lang/String 
    27: astore_2 
    28: new  #2; //class java/util/ArrayList 
    31: dup 
    32: invokespecial #3; //Method java/util/ArrayList."<init>":()V 
    35: astore_3 
    36: aload_3 
    37: ldc  #4; //String 
    39: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 
    44: pop 
    45: aload_3 
    46: iconst_0 
    47: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 
    52: checkcast  #7; //class java/lang/String 
    55: astore 4 
    57: return 

} 

당신이 (당신은 인내심이있는 경우), 두이 볼 수 있듯이 같은.

덧붙여 말하자면, 이것은 Java 7에서 더 쉽게 될 수 있습니다. "일반 인스턴스 생성을위한 향상된 유형 유추"에 대해 Project Coinproposal이 있습니다. 최종 컷을 만드는 경우 구문은 다음과 같습니다.

List<String> test = new ArrayList<>(); 
// or 
Map<String, Object> test2 = new HashMap<>(); 

입력하기가 너무 힘들지 않습니까?

+0

코드에서 의도적으로 "정적"후에 이 발생 했습니까? 목적은 무엇입니까? – euphoria83

+0

@ euphoria83 : 은 컴파일러가 일반적인 방법임을 알리기위한 것입니다. 7 페이지 및 http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf를 참조하십시오. 의 차이가 무엇 –

+0

: 목록 X = 새로운 ArrayList를을(); 그리고 당신의 중간 기능? 그리고 첫 번째와 두 번째 예제가 다소 비슷하다고 말하면 차이점은 무엇입니까? –

3

그 중복성은 성가신 일입니다.

List<Double> doubleList = Lists.newLinkedList(); 

는 또한 Java Generics are not covariant 것을주의 :이 같은 List의를 만들 팩토리 메소드를 Google Collections보고 할 수 있습니다.

+0

Google 컬렉션은 매우 편리합니다. 감사합니다. –

관련 문제