유형 추정 및 범용 방법 - [OOP 및 Java#7]
36832 단어 computerscienceoopcodenewbiejava
다음과 같이 가정합니다.
Demo
클래스입니다.Demo
류에는 함수를 받아들여 원시 목록에 있는 새 항목 목록으로 되돌려주는 map
방법이 있습니다. 그러나 이 함수는 수정됩니다.import java.util.List;
import java.util.ArrayList;
import java.util.function.Function;
class Demo<T> {
List<T> list;
Demo(List<T> list) {
this.list = list;
}
<U> Demo<U> map(Function<? super T, ? extends U> f) {
List<U> answer = new ArrayList<U>();
for (T item : this.list) {
answer.add(f.apply(item));
}
return new Demo<U>(answer);
}
}
추가 정보<T> , <? super T, ? extends U>
등.화목하다
Function<...>
Function<Object, Integer> f = x -> x.hashCode();
f
는 수신Object
유형의 입력과 출력Integer
의 함수입니다.// turns an input object into its hash value representation
Function<Object, Integer> f = x -> x.hashCode();
// List of strings
List<String> strings = new ArrayList<String>();
strings.add("a");
strings.add("b");
// Q1 - 5
Demo<Integer> list = new Demo<String>(strings).map(f);
Demo<Number> list = new Demo<String>(strings).map(f);
Demo<Object> list = new Demo<String>(strings).map(f);
Demo<String> list = new Demo<String>(strings).map(f);
Demo<> list = new Demo<String>(strings).map(f);
// Q6 - 10
(Demo<Integer>) new Demo<String>(strings).map(f);
(Demo<Number>) new Demo<String>(strings).map(f);
(Demo<Object>) new Demo<String>(strings).map(f);
(Demo<String>) new Demo<String>(strings).map(f);
(Demo) new Demo<String>(strings).map(f);
답안
1 좋아, 6 좋아.
2, OK, 7 땡.
3, OK, 8 오류.
4 오류 9 오류
5 땡, 10 오케이.
분석
관련된 유형 파라미터를 설명해 봅시다. 이것은 일을 분명히 할 것입니다.
구조 함수를 사용하여
Demo
대상을 만들 때, 특정한 유형의 항목을 포함하는 목록을 전송해야 합니다.항목의 유형은 T
클래스의 유형Demo
이 됩니다.그래서// note that map() method is not applied here
// T is replaced by String
Demo<String> listOfString = new Demo<String>(Arrays.asList("a", "b"));
// T is replaced by Integer
List<Integer> myList = new ArrayList<Integer>();
myList.add(1);
Demo<Integer> listOfInteger = new Demo<Integer>(myList));
실제로 Demo
클래스는 다음과 같습니다.class Demo<String> {
List<String> list;
Demo(List<String> list) {
this.list = list;
}
//...
}
class Demo<Integer> {
List<Integer> list;
Demo(List<Integer> list) {
this.list = list;
}
//...
}
불변성 관계로 인해 다음과 같은 상황이 발생하지 않도록 주의하십시오.// ERROR
Demo<Number> listOfNumber = new Demo<Integer>(Arrays.asList(1, 1));
이제 질문 하나 볼게요. - 5.숙제에 관한 문제
문장 1부터 5까지 다음을 시도합니다.
Demo
의 구조 함수 및 문자열 목록 전송.map(f)
방법을 호출하고 새로운 Demo
실례건조사
Demo<Integer> list =
new Demo<String>(strings)
.map(f);
여기에는 문제가 없습니다. 왜냐하면 우리는
Demo
에서 T
이 Demo
라고 성명했고 문자열 목록을 전달했기 때문입니다.구조 함수에 대해 말하자면, 우리는 정확한 유형의 매개 변수를 전달하고 있으며, 이것은 String
의 실례를 되돌려 줄 것이다.Demo<String>
메서드
Demo<Integer> list = new Demo<String>(strings)
.map(f);
여기가 헷갈리는 곳이야.중요한 관련 코드 세션을 나열합니다.
Function<Object, Integer> f = x -> x.hashCode();
class Demo<T> {
List<T> list;
Demo(List<T> list) {
this.list = list;
}
<U> Demo<U> map(Function<? super T, ? extends U> f) {
List<U> answer = new ArrayList<U>();
for (T item : this.list) {
answer.add(f.apply(item));
}
return new Demo<U>(answer);
}
}
앞에서 구조 함수에 대한 토론에서 우리는 우리가 그 중에서 호출하는 방법map
의 실례가 map
인 것을 안다.따라서 호출
Demo<String>
시 map
클래스 중의 T
은 여전히 Demo
이다.따라서 String
클래스를 볼 수 있습니다. 여기서 Demo
클래스는 T
클래스로 바뀝니다.class Demo<String> {
List<String> list;
Demo(List<String> list) {
this.list = list;
}
<U> Demo<U> map(Function<? super String, ? extends U> f) {
List<U> answer = new ArrayList<U>();
for (String item : this.list) {
answer.add(f.apply(item));
}
return new Demo<U>(answer);
}
}
현재, String
방법은 여전히 두 가지'미지수'가 있다.map
?
U
방법을 호출할 때, 우리는 함수map
를 전송하는데, 이 함수는 f
방법에'제공'유형을 주고, 이 방법이 map
매개 변수로 받아들이는 것에 동의해야 한다.우리 자세히 비교해 봅시다...
Function<Object, Integer> f = x -> x.hashCode();
<U> Demo<U> map(Function<? super String, ? extends U> f)
// for better visual, I will add spaces to align them
Function< Object, Integer>
<U> Demo<U> map(Function<? super String, ? extends U>)
입력함수
f
의 Object
는 f
의 첫 번째 매개 변수에 대응한다? super String
.map
뭘까요...
?
becomesObject
.- Hence
Object super String
- Which is itself a valid statement as
Object
is indeed a parent ofString
<U> Demo<U> map(Function<Object super String, ? extends U>)
출력함수
?
의 Integer
는 f
의 두 번째 매개 변수에 대응한다? extends U
.map
뭘까요...
?
becomesInteger
, which is unsurprising- This is fine because
?
is a wildcard and it can be of any type
<U> Demo<U> map(Function<Object super String, Integer extends U>)
?
뭘까요...명확한 설명이 없기 때문에
U
, 컴파일러는 추정할 것이다U
.그것은 어떻게 추리를 진행합니까?
U
는 지정된 변수 유형이 됩니다.또는 U
?
는 LHS(Lature English Management)에서 지정한 유형이 됩니다.또는 U
은U
의 유형이 됩니다.임무
마지막으로 몇 가지 문제를 봅시다
// Q1 - 5
Demo<Integer> list = new Demo<String>(strings).map(f);
Demo<Number> list = new Demo<String>(strings).map(f);
Demo<Object> list = new Demo<String>(strings).map(f);
Demo<String> list = new Demo<String>(strings).map(f);
Demo<> list = new Demo<String>(strings).map(f);
Q1-4에 대해 유형 추리를 통한 논리?
는 각각 U
, Integer
, Number
, Object
로 바뀐다.Q2로만 설명
Demo<Number> map(Function<Object super String, Integer extends Number> f)
String
자체가 유효한 문장입니다. Integer extends Number
은Number
의 부급이기 때문입니다.따라서 출력에 주목하면 Q2의 방법 호출은 하나
Integer
로 되돌아갈 것이다. 이것은 Demo<Number>
에 분배될 것이다. 아주 좋다!1분기와 3분기도 마찬가지다.
왜 Q3가 틀렸어요?
Demo<String> map(Function<Object super String, Integer extends String> f)
Demo<Number> list
를 U
로 바꾸면서 우리는 이 모순을 얻었다.String
Integer extends String
의 상위 항목이 아니기 때문에 유효하지 않습니다.incompatible types: inference variable U has incompatible bounds,
equality constraints: java.lang.String
lower bounds: java.lang.Integer
문제 5도 엉터리 진술이다.이것은 우리가 범용 유형의 대상을 설명할 때 유형 파라미터를 제공해야 하기 때문이다.
유형 변환 문제
// Q6 - 10
(Demo<Integer>) new Demo<String>(strings).map(f);
(Demo<Number>) new Demo<String>(strings).map(f);
(Demo<Object>) new Demo<String>(strings).map(f);
(Demo<String>) new Demo<String>(strings).map(f);
(Demo) new Demo<String>(strings).map(f);
주요 논리는 이미 이전 절에서 해석되었다.여기서 유일한 차이점은 우리가 형식 변환을 실행하는 것이지 되돌아오는 대상을 변수에 분배하는 것이 아니라는 것이다.또는 반환된 대상을 변수에 부여하기 전에 형식 변환을 합니다.Q1-5와 유사하게, 우리가 계속해서 어떤 내용을 되돌리기 전에, 우리는 여전히
String
가 무엇인지 추정해야 한다.값 부여 문장과 달리 컴파일러는 추정할 수 있는 변수가 없습니다.따라서 두 번째 전략, 즉 방법 매개 변수로 추정하는 것을 사용할 것이다.기억해라, 우리는 있다
Integer
따라서 유일하게 언급해야 할 것은U
이다.map(<Object super String, ? extends U>)
이?
로 결정되었으므로 ?
이Integer
여야 합니다.이제 저희가 생겼어요.
Demo<Integer> map(Function<Object super String, Integer extends Integer> f)
U
은Integer
이므로 U
방법의 반환 유형은 Integer
으로 변경됩니다.범형이 변하지 않는다는 것을 알면 Q6(과 Q10)를 제외한 나머지 문장에 문제가 있다는 것을 알게 될 것이다.
Q7 데모 사용
// ERROR
(Demo<Number>) Demo<Integer> ...
// Or view it as
List<Integer> listOfIntegers = new ArrayList<Integer>();
listOfIntegers.add(1);
listOfIntegers.add(2);
Demo<Number> list = new Demo<Integer>(listOfIntegers);
컴파일러 오류:incompatible types: Demo<java.lang.Integer>
cannot be converted to Demo<java.lang.Number>
Q10에 대해 컴파일할 수 있지만, 이것은 좋은 방법이 아니다. 왜냐하면 우리는 되돌아오는 대상을 rawtype에 분배하기 때문이다.List<Integer> listOfIntegers = new ArrayList<Integer>();
listOfIntegers.add(1);
listOfIntegers.add(2);
// View it as
Demo list = new Demo<Integer>(listOfIntegers);
현재map
는 Demo<Integer>
유형에 속한다.대상 유형 및 유형 증명
나의 위의 해석은 Oracle's java tutorial에서 소개한 기술 용어를 사용하지 않았다.다음은 내가 어떻게 정확한 용어를 사용하여 그것을 해석할 것인가이다.
list
Demo
Demo<Number> list = new Demo<String>(strings).map(f);
타겟 유형입니다.Demo<Number>
의 값을 되돌려주기 때문에 컴파일러는 유형 매개 변수Demo<Number>
가 반드시 값Demo<U>
이어야 한다고 추정한다U
공구서류
Oracle's Java tutorial on Type Inference
Reference
이 문제에 관하여(유형 추정 및 범용 방법 - [OOP 및 Java#7]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tlylt/type-inference-and-generic-methods-oop-java-7-3leg텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)