Java 7에서 다이아몬드 연산자 (<>)의 요점은 무엇입니까?


446

Java 7의 다이아몬드 연산자는 다음과 같은 코드를 허용합니다.

List<String> list = new LinkedList<>();

그러나 Java 5/6에서는 간단히 작성할 수 있습니다.

List<String> list = new LinkedList();

타입 삭제에 대한 나의 이해는 이것들이 정확히 동일하다는 것입니다. 어쨌든 제네릭은 런타임에 제거됩니다.

왜 다이아몬드를 전혀 귀찮게합니까? 어떤 새로운 기능 / 유형 안전이 허용됩니까? 새로운 기능을 제공하지 않으면 왜 기능으로 언급합니까? 이 개념에 대한 나의 이해가 잘못 되었습니까?


4
Java는 메소드 팩토리에 대해 유형 유추를 수행하므로 정적 팩토리 메소드를 사용하는 경우에는 문제가되지 않습니다.
Brian Gordon

당신이 경고를 사용하지 않도록 설정하면 실제로는 쓸모 ... :) 같은 날
Renetik

3
답변이되었지만 Java 튜토리얼 (페이지 중간)에 있습니다. docs.oracle.com/javase/tutorial/java/generics/…
Andreas Tasoulas

dZone 에 대한 좋은 기사 .
R. Oosterholt

2
내 관점은 List <String> list = new LinkedList <왼쪽의 유형이 무엇이든> (); 즉 일반적인 그것을 유지
Viktor Mellgren

답변:


497

문제

List<String> list = new LinkedList();

왼쪽에, 당신은 사용하고 있다는 점이다 일반적인 유형의 List<String>오른쪽에 당신이 사용하는 원시 유형을 LinkedList. Java의 원시 유형은 사실상 제네릭 이전 코드와의 호환성을 위해서만 존재하며 반드시 필요한 경우가 아니면 새 코드에서 사용해서는 안됩니다.

이제 Java에 처음부터 제네릭이 있고 제네릭을 갖기 LinkedList전에 처음 생성 된 유형이없는 경우 제네릭 유형의 생성자가 자동으로 왼쪽에서 유형 매개 변수를 유추하도록 만들 수 있습니다. 가능하면 과제의 손. 그러나 이전 버전과의 호환성을 위해 원시 유형과 일반 유형을 다르게 처리해야합니다. 잎 그들은 만들 필요가 약간 다른 그 유형 매개 변수 ... 다이아몬드 연산자를 반복 할 필요없이 일반 객체의 새로운 인스턴스를 선언하지만, 똑같이 편리한 방법을.

의 원래 예제 List<String> list = new LinkedList()에서 컴파일러는 해당 할당에 대한 경고를 생성해야합니다. 이걸 고려하세요:

List<String> strings = ... // some list that contains some strings

// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);

제네릭은 잘못된 일을하지 않도록 컴파일 타임을 보호하기 위해 존재합니다. 위의 예에서 raw 유형을 사용하면이 보호 기능을 사용할 수 없으며 런타임시 오류가 발생합니다. 이것이 원시 유형을 사용하지 않아야하는 이유입니다.

// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);

그러나 다이아몬드 연산자를 사용하면 할당의 오른쪽을 매개 변수를 다시 입력하지 않고도 왼쪽과 동일한 형식 매개 변수를 가진 실제 일반 인스턴스로 정의 할 수 있습니다. 원시 유형을 사용하는 것과 거의 동일한 노력으로 제네릭의 안전을 유지할 수 있습니다 .

이해해야 할 핵심은 원시 유형 (없음 <>)을 일반 유형과 동일하게 취급 할 수 없다는 것입니다. 원시 형식을 선언하면 제네릭의 이점과 형식 검사가 없습니다. 또한 제네릭은 Java 언어의 범용 부분 이라는 점을 명심해야합니다 Collection. s 의 no-arg 생성자에만 적용되는 것은 아닙니다 !


31
이전 버전과의 호환성은 훌륭하지만 복잡성을 희생하지는 마십시오. Java 7에서 -compatibility컴파일러 스위치를 도입 할 수없는 이유는 무엇입니까? 없는 경우 javac모든 원시 유형을 금지하고 엄격하게 일반 유형 만 시행합니까? 이렇게하면 코드가 덜 장황하게됩니다.
Rosdi Kasim

3
@ Rosdi : 합의, 새로운 코드에서 원시 유형이 필요하지 않습니다. 그러나 명령 파일을 사용하여 (mis) 대신 소스 파일에 Java 버전 번호를 포함시키는 것이 좋습니다. 내 대답을 참조하십시오.
maaartinus

37
나는 당신이 같은 라인에서 정의하고 인스턴스화하지 않는 한 다이아몬드 사용을 개인적으로 좋아하지 않습니다. List<String> strings = new List<>()괜찮습니다. private List<String> my list;하지만를 정의한 다음 인스턴스화하는 페이지를 반쯤 내리면 my_list = new List<>()멋지지 않습니다! 내 목록에 다시 무엇이 포함됩니까? 아, 정의를 찾아 보도록하겠습니다. 갑자기, 다이아몬드 지름길의 장점은 안녕입니다.
rmirabelle

11
@rmirabelle 어떻게 다른가 : my_list = getTheList()? 이런 종류의 문제를 처리하는 더 좋은 방법이 몇 가지 있습니다. 1. 마우스로 가리키면 변수 유형을 보여주는 IDE를 사용하십시오. 2.보다 의미있는 변수 이름 private List<String> strings을 사용하십시오. 실제로 선언하지 않으면 변수 선언과 초기화를 분리하지 마십시오.
Natix

1
@Morfidon : 네, 자바 8. 여전히 유효한의 나는 확신 당신이있어 해야 경고를 받고있을.
ColinD
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.