1. 개요
이 빠른 사용방법(예제)에서는 <?> 와 <? 의 유사점과 차이점을 확인할 수 있습니다 . Java Generics 에서 Object> 를 확장합니다 .
그러나 이것은 고급 주제이므로 문제의 핵심으로 들어가기 전에 주제에 대한 기본적인 이해 를 얻는 것이 필수적 입니다.
2. 제네릭의 배경
컴파일 시간 오류를 제거하고 유형 안전성을 강화하기 위해 JDK 5에 Generics가 도입되었습니다. 이 추가 유형 안전성은 일부 사용 사례에서 캐스팅을 제거하고 프로그래머가 일반 알고리즘을 작성할 수 있도록합니다.이 두 알고리즘 모두 더 읽기 쉬운 코드로 이어질 수 있습니다.
예를 들어 JDK 5 이전 버전에서는 캐스팅을 사용하여 List의 요소로 작업해야합니다. 이것은 차례로 특정 클래스의 런타임 오류를 생성했습니다.
List aList = new ArrayList();
aList.add(new Integer(1));
aList.add("a_string");
for (int i = 0; i < aList.size(); i++) {
Integer x = (Integer) aList.get(i);
}
이제이 코드에는 해결해야 할 두 가지 문제가 있습니다.
- aList 에서 값을 추출하려면 명시 적 캐스트가 필요 합니다 . 유형은 왼쪽의 변수 유형에 따라 다릅니다. 이 경우에는 정수
- a_string 을 Integer 로 캐스트하려고 할 때 두 번째 반복에서 런타임 오류가 발생합니다.
Generics는 우리에게 역할을합니다.
List<Integer> iList = new ArrayList<>();
iList.add(1);
iList.add("a_string"); // compile time error
for (int i = 0; i < iList.size(); i++) {
int x = iList.get(i);
}
컴파일러는 Integer 유형 의 List 에 a_string 을 추가 할 수 없다고 알려줍니다 . 이는 런타임에 찾는 것보다 낫습니다.
컴파일러는 이미 알고 있기 때문에 또한, 명시 적 캐스팅이 필요하지 않습니다 IList의이 보유하고 정수 의. 또한 Unboxing의 마법으로 인해 Integer 유형 도 필요하지 않았 으며 원시 형식으로 충분합니다.
3. 제네릭의 와일드 카드
제네릭에서 알 수없는 유형을 나타 내기 위해 물음표 또는 와일드 카드가 사용됩니다. 세 가지 형식이 있습니다.
- Unbounded Wildcards : List <?> 는 알 수없는 유형의 List을 나타냅니다.
- 상한 와일드 카드 : List <? extends Number> 는 Number 또는 Integer 및 Double 과 같은 하위 유형 의 List을 나타냅니다.
- 하한 와일드 카드 : List <? super Integer> 는 Integer 또는 그 수퍼 유형 Number 및 Object List을 나타냅니다.
이제 Object 는 Java의 모든 유형의 고유 한 상위 유형이므로 알려지지 않은 유형을 나타낼 수도 있다고 생각하고 싶을 것입니다. 즉, List <?> 와 List <Object> 는 동일한 용도로 사용할 수 있습니다. 그러나 그들은 그렇지 않습니다.
다음 두 가지 방법을 고려해 보겠습니다.
public static void printListObject(List<Object> list) {
for (Object element : list) {
System.out.print(element + " ");
}
}
public static void printListWildCard(List<?> list) {
for (Object element: list) {
System.out.print(element + " ");
}
}
Integer List이 주어지면 다음 과 같이 말하십시오.
List<Integer> li = Arrays.asList(1, 2, 3);
printListObject (li) 는 컴파일되지 않으며 다음 오류가 발생합니다.
The method printListObject(List<Object>) is not applicable for the arguments (List<Integer>)
반면 printListWildCard (li) 는 컴파일 되어 콘솔에 1 2 3 을 출력 합니다.
4. <?> 및 <? Extends Object> – 유사점
위의 예에서, 우리가 메서드 서명을 변경하는 경우 printListWildCard 에 :
public static void printListWildCard(List<? extends Object> list)
printListWildCard (List <?> list) 와 동일한 방식으로 작동합니다 . 이는 Object 가 모든 Java 객체의 상위 유형이고 기본적으로 모든 것이 Object 확장 한다는 사실 때문입니다 . 그래서하는 List 의 정수 들뿐만 아니라 처리됩니다.
즉, 그것은 것을 의미 ? 그리고 ? extends Object 는이 예제에서 동의어입니다 .
대부분의 경우 사실 이지만 몇 가지 차이점도 있습니다 . 다음 섹션에서 살펴 보겠습니다.
5. <?> 및 <? Extends Object> – 차이점
수정 가능한 유형은 컴파일 시간에 유형이 지워지지 않는 유형입니다. 즉, 수정 불가능한 유형의 런타임 표현은 일부가 지워지기 때문에 컴파일 시간에 비해 정보가 적습니다.
일반적으로 매개 변수화 된 유형은 수정할 수 없습니다. 이는 List <String> 및 Map <Integer, String> 을 수정할 수 없음을 의미합니다. 컴파일러는 해당 유형을 지우고 각각 List 및 Map 으로 처리합니다 .
이 규칙에 대한 유일한 예외는 제한되지 않은 와일드 카드 유형입니다. 이는 List <?> 및 Map <?,?> 을 수정할 수 있음을 의미 합니다.
반면에 List <? extends Object> 는 수정할 수 없습니다 . 미묘하지만 이것은 주목할만한 차이점입니다.
수정 불가능한 유형은 instanceof 연산자 또는 배열의 요소 와 같은 특정 상황 에서 사용할 수 없습니다 .
따라서 다음과 같이 작성하면
List someList = new ArrayList<>();
boolean instanceTest = someList instanceof List<?>
이 코드는 컴파일되고 instanceTest 는 true 입니다.
그러나 List <? 에서 instanceof 연산자를 사용하면 ? Object> 확장 :
List anotherList = new ArrayList<>();
boolean instanceTest = anotherList instanceof List<? extends Object>;
그런 다음 라인 2는 컴파일되지 않습니다.
마찬가지로 아래 스 니펫에서 1 행은 컴파일되지만 2 행은 컴파일되지 않습니다.
List<?>[] arrayOfList = new List<?>[1];
List<? extends Object>[] arrayOfAnotherList = new List<? extends Object>[1]
6. 결론
이 짧은 사용방법(예제)에서 <?> 및 <? 의 유사점과 차이점을 확인했습니다 . Object>를 확장합니다 .
대부분 유사하지만 수정 가능 여부에 따라 두 가지 사이에는 미묘한 차이가 있습니다.
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/java-generics-vs-extends-object
'Java' 카테고리의 다른 글
Java에서 숫자를 N 소수 자릿수로 반올림하는 방법 (0) | 2021.04.16 |
---|---|
Java의 List에서 모든 중복 제거 (0) | 2021.04.16 |
Spring REST 컨트롤러에서 HTTP 헤더를 읽는 방법 (0) | 2021.04.15 |
Spring MVC의 커스텀 데이터 바인더 (0) | 2021.04.15 |
Spring 컨트롤러에서 List 유효성 검사 (0) | 2021.04.15 |