일반 반환 유형 상한 - 인터페이스 대 클래스 - 놀랍도록 유효한 코드
이것은 서드파티 라이브러리 API의 실제 예이지만 단순화되어 있습니다.
Oracle JDK 8u72를 사용하여 컴파일
다음 두 가지 방법을 고려합니다.
<X extends CharSequence> X getCharSequence() {
return (X) "hello";
}
<X extends String> X getString() {
return (X) "hello";
}
두 사람 모두 "확인되지 않은 출연자" 경고를 보고한다. 왜 그런지 알겠다.나를 당혹스럽게 하는 것은 왜 전화를 할 수 있는가 하는 것이다.
Integer x = getCharSequence();
파일일 할???는 이 .Integer
does does does does 。CharSequence
의 콜
Integer y = getString();
(예상대로) 에러를 표시합니다.
incompatible types: inference variable X has incompatible upper bounds java.lang.Integer,java.lang.String
누가 왜 이 행동이 유효한 것으로 간주되는지 설명해 줄 수 있나요?어떻게 도움이 될까요?
클라이언트는 이 콜이 안전하지 않은지 모르고 클라이언트의 코드가 경고 없이 컴파일됩니다.컴파일이 그것에 대해 경고하지 않거나 오류를 발생시키지 않는 이유는 무엇입니까?
또, 이 예와 어떻게 다른가.
<X extends CharSequence> void doCharSequence(List<X> l) {
}
List<CharSequence> chsL = new ArrayList<>();
doCharSequence(chsL); // compiles
List<Integer> intL = new ArrayList<>();
doCharSequence(intL); // error
하려고 하다List<Integer>
에러가 표시됩니다.
method doCharSequence in class generic.GenericTest cannot be applied to given types; required: java.util.List<X> found: java.util.List<java.lang.Integer> reason: inference variable X has incompatible bounds equality constraints: java.lang.Integer upper bounds: java.lang.CharSequence
되고 있는 는, 왜 「」 「」 「」 「」 「」가 되는 것입니까.Integer x = getCharSequence();
안그래?
CharSequence
는 입니다.interface
따라서,SomeClass
does does does does 。CharSequence
수 것 .
class SubClass extends SomeClass implements CharSequence
그러므로 당신은 글을 쓸 수 있다.
SomeClass c = getCharSequence();
는, 「유추형」이 「유추형」이기 때문입니다.X
입니다.SomeClass & CharSequence
.
는 좀 요.Integer
Integer
이지만, final
이 규칙들에서는 아무런 역할도 하지 않습니다.를 들면 '어리다'라고 쓰면 요.
<T extends Integer & CharSequence>
반,는String
아니다interface
할 수 SomeClass
을 String
java는 클래스에 대해 멀티 테넌스를 지원하지 않기 때문입니다.
★List
예를 들어, 제네릭이 공변량도 아니고 반변량도 아니라는 점을 기억해야 합니다., ,, 약의 X
는 의 입니다.Y
,List<X>
서브타입도 슈퍼타입도 아니다.List<Y>
.부터Integer
does does does does 。CharSequence
, 는 사용할 수 .List<Integer>
안에서doCharSequence
★★★★★★ 。
단, 컴파일 할 수 있습니다.
<T extends Integer & CharSequence> void foo(List<T> list) {
doCharSequence(list);
}
를 반환하는 메서드가 있는 경우List<T>
음음음같 뭇매하다
static <T extends CharSequence> List<T> foo()
할수있습니다
List<? extends Integer> list = foo();
Integer & CharSequence
은 '아형'의 입니다.Integer
.
은 여러 할 때 암묵적으로 " " " " " " " " " ).<T extends SomeClass & CharSequence>
를 참조해 주세요.
상세한 것에 대하여는, JLS 의 각 부분으로부터 타입 바운드의 구조를 설명합니다.예를 들어, 복수의 인터페이스를 포함할 수 있습니다.
<T extends String & CharSequence & List & Comparator>
단, 첫 번째 바인드만 비인터페이스일 수 있습니다.
되기 전에 컴파일러에 .X
Integer & CharSequence
이런 타입은 느낌이 이상해요 왜냐하면Integer
최종적인 것이지만 자바에서는 완전히 유효한 타입입니다.그 후, 로 보내집니다.Integer
그건 완벽하게 괜찮아요.
에는 1개의 가능한 값이 있습니다.Integer & CharSequence
입력:null
. 다음과 같은 구현:
<X extends CharSequence> X getCharSequence() {
return null;
}
다음 할당이 작동합니다.
Integer x = getCharSequence();
이러한 가능한 가치 때문에, 비록 그것이 명백히 쓸모없다고 해도, 그 과제가 틀릴 이유는 없다.경고는 도움이 될 것이다.
진짜 문제는 API이지 콜사이트가 아닙니다
사실, 저는 최근에 이 API 디자인 안티 패턴에 대해 블로그에 글을 올렸습니다.임의의 유형을 반환하는 일반적인 방법을 설계하지 마십시오.추정된 유형이 전달되는 것을 (거의) 보장할 수 없기 때문입니다.예외는 다음과 같은 방법입니다.Collections.emptyList()
리스트의 공허함(및 범용 타입 삭제)이, 에 대한 추론이 있는 경우.<T>
동작합니다.
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
언급URL : https://stackoverflow.com/questions/36402646/generic-return-type-upper-bound-interface-vs-class-surprisingly-valid-code
'IT이야기' 카테고리의 다른 글
Maven: 상대 경로로 항아리에 종속성을 추가합니다. (0) | 2022.05.27 |
---|---|
Vue.js는 항상 마지막 항목을 어레이에서 삭제합니다. (0) | 2022.05.27 |
Vue + Vuetify에서 스낵바를 글로벌 구성 요소로 사용 (0) | 2022.05.27 |
자바에서 바이트 배열을 16진수로 변환하는 방법? (0) | 2022.05.26 |
index.html이 Javascript를 로드하지 않을 경우 Vue 앱을 실행하는 방법은? (0) | 2022.05.26 |