형식 앞에 * 배치 * 할 때 생성자 형식 인수는 무엇을 의미합니까?
나는 최근 에이 특이한 (나에게) 자바 구문을 보았습니다 ... 예는 다음과 같습니다.
List list = new <String, Long>ArrayList();
<String, Long>
형식 인수 의 위치를 확인하십시오 . 형식이 정상이 아니라 이전입니다. 나는이 구문을 본 적이 없다는 것을 인정하지 않습니다. 또한 ArrayList
1이 있을 때 2 개의 유형 인수 가 있습니다.
타입 인자의 위치는 타입 뒤에 넣는 것과 같은 의미입니까? 그렇지 않은 경우 다른 위치 지정은 무엇을 의미합니까?
ArrayList
1 개만 있을 때 2 개의 형식 인수를 갖는 것이 합법적 인 이유는 무엇 입니까?
예를 들어 일반적인 장소를 검색했습니다. Angelika Langer와 여기에 있지만 ANTLR 프로젝트의 Java 문법 파일에있는 문법 규칙 외에는이 구문에 대한 언급이 없습니다.
일반 생성자 호출
이것은 비정상적으로 괜찮지 만 완전히 유효한 Java입니다. 이해하려면 클래스에 일반 생성자가있을 수 있음을 알아야합니다. 예를 들면 다음과 같습니다.
public class TypeWithGenericConstructor {
public <T> TypeWithGenericConstructor(T arg) {
// TODO Auto-generated constructor stub
}
}
제네릭 생성자를 통해 클래스를 인스턴스화 할 때 유형 인수를 명시 적으로 지정할 필요가 없다고 생각합니다. 예를 들면 다음과 같습니다.
new TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));
지금 T
은 분명하다 LocalDate
. 그러나 Java가 유형 인수를 유추 (추론) 할 수없는 경우가있을 수 있습니다. 그런 다음 질문의 구문을 사용하여 명시 적으로 제공합니다.
new <LocalDate>TypeWithGenericConstructor(null);
물론 우리는 그것이 가독성이나 어떤 이유로 든 도움이된다고 생각되면 필요하지 않더라도 공급할 수도 있습니다.
new <LocalDate>TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));
귀하의 질문에 java.util.ArrayList
생성자를 호출하는 것 같습니다 . 그 생성자는 일반적인 것이 아닙니다 ( ArrayList
클래스 만 클래스입니다. 다른 것입니다). Java가 사용되지 않을 때 호출에 유형 인수를 제공 할 수있는 이유는 아래 편집을 참조하십시오. 내 이클립스는 나에게 경고를 준다 .
ArrayList 유형의 일반이 아닌 생성자 ArrayList ()에 사용되지 않은 유형 인수; 인수로 매개 변수화해서는 안됩니다.
그러나 오류는 아니며 프로그램이 정상적으로 실행됩니다 ( List
및 ArrayList
에 대한 유형 인수가 누락되었다는 경고가 표시 되지만 다시 다른 이야기입니다).
제네릭 클래스와 제네릭 생성자
타입 인자의 위치는 타입 뒤에 넣는 것과 같은 의미입니까? 그렇지 않은 경우 다른 위치 지정은 무엇을 의미합니까?
아니요, 다릅니다. 유형 ( ) 다음 의 일반적인 유형 인수 ArrayList<Integer>()
는 일반 클래스에 대한 것 입니다. 이전 의 형식 인수 는 생성자에 대한 것 입니다.
두 가지 형태를 결합 할 수도 있습니다.
List<Integer> list = new <String, Long>ArrayList<Integer>();
목록이 Integer
객체를 저장한다는 것을 알 수 있기 때문에 이것을 조금 더 올바르게 고려할 것 <String, Long>
입니다 (물론 여전히 의미가없는 것을 선호합니다 ).
ArrayList에 1 만있을 때 2 개의 유형 인수를 갖는 것이 왜 합법적인가요?
첫째, 형식 앞에 형식 인수를 제공하면 클래스가 아닌 생성자에 올바른 숫자를 제공해야하므로 클래스에있는 형식 인수의 수와 관련이 없습니다 ArrayList
. 그것은 실제로이 경우 생성자가 형식 인수를 취하지 않기 때문에 아무것도 제공하지 않아야 함을 의미합니다 (일반적이지 않음). 어쨌든 어떤 것을 공급할 때, 그것들은 무시되므로, 얼마나 많이 또는 얼마나 적게 공급하든 문제가되지 않습니다.
무의미한 유형 인수가 허용되는 이유는 무엇입니까?
링크에 대한 @Slaw 덕분에 편집 : Java는 모든 메소드 호출에서 유형 인수를 허용합니다. 호출 된 메소드가 제네릭이면 유형 인수가 사용됩니다. 그렇지 않으면 무시됩니다. 예를 들면 다음과 같습니다.
int length = "My string".<List>length();
예, 터무니 없습니다. JLS (Java Language Specification)는 15.12.2.1에 다음과 같은 정당성을 제공합니다.
이 규칙은 호환성 문제와 대체 가능성 원칙에서 비롯됩니다. 인터페이스 또는 수퍼 클래스는 하위 유형과 독립적으로 생성 될 수 있으므로 일반 메소드를 일반이 아닌 메소드로 대체 할 수 있습니다. 그러나 형식 인수를 명시 적으로 전달하는 호출을 포함하여 일반 메소드에 대한 호출에는 대체 (일반적이지 않은) 메소드가 적용 가능해야합니다. 그렇지 않으면 아형은 생성 된 슈퍼 타입으로 대체 할 수 없습니다.
이 인수는 생성자를 직접 재정의 할 수 없으므로 생성자를 보유하지 않습니다. 그러나 이미 복잡한 규칙을 너무 복잡하게 만들지 않기 위해 동일한 규칙을 원한다고 가정합니다. 어쨌든, 인스턴스화에 관한 15.9.3 절과 new
두 번 이상은 15.12.2를 참조한다.
연결
- 코드 자바의 제네릭 생성자
- JLS 15.9.3. 생성자와 인수의 선택
- JLS 15.12.2.1. 잠재적으로 적용 가능한 방법 식별
- 모든 메소드 호출에서 유형 감시를 허용하는 요점은 무엇입니까?
분명히 일반적인 것이 아닌 메소드 / 생성자 앞에 원하는 일반 매개 변수를 접두어로 추가 할 수 있습니다.
new <Long>String();
Thread.currentThread().<Long>getName();
컴파일러는 이러한 형식 인수를 실제 일반 매개 변수와 일치시킬 필요가 없으므로 신경 쓰지 않습니다.
컴파일러가 인수를 확인하자마자 불일치에 대해 불평합니다.
Collections.<String, Long>singleton("A"); // does not compile
나에게 컴파일러 버그 인 것 같습니다.
'IT story' 카테고리의 다른 글
Atom 텍스트 편집기에서 클래스 / 메소드 정의로 어떻게 이동할 수 있습니까? (0) | 2020.07.08 |
---|---|
Django 1.9에서 apps.py의 목적은 무엇입니까? (0) | 2020.07.08 |
팬더에서 데이터 정규화 (0) | 2020.07.07 |
Java에서 변수 유형을 어떻게 알 수 있습니까? (0) | 2020.07.07 |
&& (AND) 및 || (0) | 2020.07.07 |