Type dependency in Java, Part 2
Using covariance and contravariance in your Java programs
원문 : http://www.itworld.com/article/3197118/learn-java/type-dependency-in-java-part-2.html
유형 호환성을 이해하는 것은 좋은 Java 프로그램을 작성하는 기본이지만 Java 언어 요소 간의 차이점은 초급자에게는 매우 학술적으로 보일 수 있습니다. 이 두 편의 기사는 도전 과제를 해결할 준비가 된 소프트웨어 개발자를 대상으로합니다. Part 1 에서는 배열 유형과 제네릭 유형과 같은 더 단순한 요소와 특수 Java 언어 요소 인 와일드 카드 간의 공변 관계 및 반 행위 관계를 설명했습니다. Part 2에서는 Java Collections API, 제네릭 및 람다 식의 형식 종속성에 대해 설명합니다.
우리는 바로 들어가기 때문에 Part 1을 아직 읽지 않았다면 거기에서 시작하는 것이 좋습니다.
반공 진성을위한 API 예제
첫 번째 예제에서는 Java Collections API 의 Comparator
버전을 고려해야한다 java.util.Collections.sort()
. 이 메소드의 서명은 다음과 같습니다.
sort()
방법은 정렬 List
. 대개 오버로드 된 버전을 서명과 함께 사용하는 것이 더 쉽습니다.
이 경우, extends Comparable
해당 표현 sort()
필요한 메소드 비교 요소 (즉에만 호출 될 수있다 compareTo)
, 소자 형 정의 (또는 퍼에서 한 감사합니다 :? superT)
비교를 위해 제네릭 사용
분명히 그 요소가 서로 비교 될 수있는 경우에만 목록을 정렬 할 수 있습니다. 비교는 인터페이스에 compareTo
속한 단일 메소드에 의해 수행됩니다 Comparable
. compareTo
요소 클래스에 구현해야합니다 .
그러나이 유형의 요소는 한 방향으로 만 정렬 할 수 있습니다. 예를 들어 Customer
자신의 ID로 정렬 할 수 있지만 생일이나 우편 번호로 정렬 할 수는 없습니다. 의 Comparator
버전을 사용하는 sort()
것이 더 유연합니다 :
이제 우리는 요소의 클래스가 아닌 다른 Comparator
객체 를 비교 합니다. 이 일반 인터페이스에는 하나의 객체 메소드가 있습니다.
반 변형 매개 변수
객체를 두 번 이상 인스턴스화하면 다른 기준을 사용하여 객체를 정렬 할 수 있습니다. 그러나 우리는 정말로 그러한 복잡한 Comparator<? super T>
타입 파라미터를 필요로 합니까? 대부분의 경우 Comparator<T>
충분할 것입니다. 다음과 compare()
같이이 메서드를 사용 하여 List<T>
객체의 두 요소를 비교할 수 있습니다 .
그러나 더 복잡한 버전의 메소드를 사용하면 추가 Collection.sort()
사용 사례를 설정할 수 있습니다. 의 contravariant 유형 매개 변수는 Comparable
유형의 목록을 정렬하는 것을 가능하게 List<java.sql.Date>
하기 때문에, java.util.Date
의 슈퍼입니다 java.sql.Date
:
서명에서 contravariance를 생략하면 (지정되지 않았 거나 안전하지 않은 sort()
경우에만 <T>
사용됨 <?>
) 컴파일러는 마지막 줄을 유형 오류로 거부합니다.
전화하기 위해서
당신은 여분의 특색없는 클래스를 써야 할 것이다 :
추가 방법
Collections.sort()
반동 매개 변수를 갖춘 유일한 Java Collections API 메소드는 아닙니다. 같은 방법 addAll()
, binarySearch()
, copy()
, fill()
, 등이 유사한 유연하게 사용할 수 있습니다.
Collections
메소드 는 반올림 (contravariant) 결과 유형 max()
을 min()
제공합니다.
여기에서 볼 수 있듯이 형식 매개 변수는 두 개 이상의 조건을 만족시키기 위해 요청할 수 있습니다 &
. 는 extends Object
불필요한 나타날 수 있지만, 그 규정 max()
형식의 결과를 반환 Object
하지 행의 Comparable
바이트 코드에. 바이트 코드에는 형식 매개 변수가 없습니다.
의 오버로드 된 버전 max()
과는 Comparator
심지어 더 재미있다 :
이것은 max()
역행 (contravariant) 및 공변 (covariant) 유형 매개 변수를 모두가 집니다. 의 요소가있는 동안 Collection
어떤 (명시 적으로 지정하지) 형 (가능한 서로 다른) 아형이어야 Comparator
동일한 형태의 슈퍼 인스턴스화되어야한다. 컴파일러의 추론 알고리즘은이 중간 유형과 다음과 같은 호출을 구별하기 위해 많이 필요합니다.
유형 매개 변수의 박스형 바인딩
자바 컬렉션 API를 입력 의존성과 분산의 우리의 마지막 예를 들어,의는의 서명 재고 할 sort()
과를 Comparable
. 두 개의 extends
& 를 사용한다는 점에 유의하십시오 super
.
이 경우 우리는 인스턴스화를 바인딩 할 때 참조의 호환성에 관심이 없습니다. 이 sort()
메소드의 인스턴스는 구현 list
하는 클래스의 요소 로 객체를 정렬합니다 Comparable
. 대부분의 경우 정렬은 <? super T>
메서드의 서명 없이 작동 합니다.
그러나 type 매개 변수의 하한은 추가 유연성을 허용합니다. Comparable
반드시 요소 클래스에서 구현 될 필요는 없다. 수퍼 클래스에서 구현 한 것으로 충분합니다. 예 :
컴파일러는 다음 행을 받아들입니다.
그것을 거절한다.
이 거부 이유 SubClass
는 컴파일러가 매개 변수의 형식 List<SubClass>
에서 결정할 subList
형식이 형식 매개 변수로 적합하지 않기 때문입니다 T extends Comparable<T>
. 유형 SubClass
이 구현되지 않습니다 Comparable<SubClass>
. 그것은 단지 구현 Comparable<SuperClass>
합니다. 두 요소는 암시 적 공분산의 부족으로 인해 호환되지 않지만 SubClass
호환 가능합니다 SuperClass
.
우리가 사용하는 경우 반면에, <? super T>
컴파일러는 기대하지 않는 SubClass
구현하기 위해 Comparable
; 그렇게된다면 충분 SuperClass
합니다. 메서드 compareTo()
가 상속되고 개체를 SuperClass
호출 할 수 있기 때문에 충분 SubClass
합니다. <? super T>
이를 표현하여 반항을 초래합니다.
형식 매개 변수의 반 변형 액세스 변수
상한 또는 하한 은 공변 또는 반 관행 참조에 의해 참조되는 인스턴스화 의 유형 매개 변수 에만 적용됩니다 . Generic<? extends SuperType> covariantReference;
and 의 경우 Generic<? super SubType> contravariantReference;
다른 Generic
인스턴스화 객체를 만들고 참조 할 수 있습니다 .
메소드의 매개 변수 및 결과 유형 (예 : 일반 유형의 입력 및 출력 매개 변수 유형)에 대해 다른 규칙이 유효 합니다. 위에서 정의 된 SubType
대로 호환 가능한 임의의 객체를 메소드의 매개 변수 로 전달할 수 있습니다 write()
.
contravariance 때문에 매개 변수를 전달할 수 write()
있습니다. 이것은 공변 (또한 제한되지 않은) 와일드 카드 유형과 대조됩니다.
상황은 바인딩을 통해 결과 유형에 대해 변경되지 않습니다. 유형의 결과를 read()
계속 전달하며 다음 ?
과 만 호환됩니다 Object
.
마지막 행은 contravariantReference
타입 을 선언 했음에도 불구하고 에러를 발생 Generic<? super SubType>
시킵니다.
결과 유형은 참조 유형이 명시 적으로 변환 된 후에 만 다른 유형과 호환됩니다.
이전 목록의 예제는 유형 변수에 대한 읽기 또는 쓰기 액세스가 parameter
메소드 (읽기 및 쓰기) 또는 직접 (예제의 데이터)에 관계없이 동일한 방식으로 작동 함 을 보여줍니다 .
매개 변수 유형의 변수 읽기 및 쓰기
표 1은 Object
모든 클래스와 와일드 카드가 호환되기 때문에 항상 변수로 읽는 것이 가능하다는 것을 보여줍니다 Object
. 글 쓰는 것은 와일드 카드와 호환되지 Object
않기 때문에, 적절한 캐스팅을 한 후에 반작용적인 참조를 통해서만 가능합니다 Object
. 공변 관계가없는 변수로 형변환하지 않고 읽는 것이 가능합니다. contravariant 참조로 작성하는 것이 가능합니다.
1 번 테이블. 유형 변수에 대한 읽기 및 쓰기 액세스parameter
판독 (입력) | readObject | writeObject | 수퍼 유형을 읽는다. | 수퍼 유형 작성 | 하위 유형 읽기 | 하위 유형 작성 |
와일드 카드? | 승인 | 오류 | 캐스트 | 캐스트 | 캐스트 | 캐스트 |
공변량?extends | 승인 | 오류 | 승인 | 캐스트 | 캐스트 | 캐스트 |
반항적 인?super | 승인 | 캐스트 | 캐스트 | 캐스트 | 캐스트 | 승인 |
표 1의 행은 참조 정렬을 나타내고 액세스 할 데이터 유형에 대한 열을 나타 냅니다. "supertype"W "subtype"표제는 와일드 카드 범위를 나타냄니다. "캐스트"항목은 참조를 캐스팅해야 함을 의미합니다. 마지막 4 개의 열에서 "OK"의 인스턴스는 공분산 및 반공립에 대한 일반적인 경우를 나타냅니다.
자세한 설명과 함께 테이블에 대한 체계적인 테스트 프로그램에 대해서는이 기사의 끝 부분을 참조하십시오.
객체 만들기
한편으로는 추상적이기 때문에 와일드 카드 유형의 객체를 만들 수 없습니다. 한편, 무제한의 와일드 카드 형의 배열 객체를 작성할 수 있습니다. 그러나 다른 일반 인스턴스화의 객체는 작성할 수 없습니다.
배열의 공분산으로 인해 와일드 카드 배열 유형 Generic<?>[]
은 모든 인스턴스화의 배열 유형의 상위 유형입니다. 따라서 위 코드의 마지막 줄에 할당이 가능합니다.
generic 클래스 내에서는 type 매개 변수의 객체를 만들 수 없습니다. 예를 들어, 구현의 ArrayList
생성자에서 배열 객체는 Object[]
생성시 유형이어야합니다 . 그런 다음이를 유형 매개 변수의 배열 유형으로 변환 할 수 있습니다.
더 안전한 해결 방법 Class
을 위해 실제 형식 매개 변수의 값을 생성자에 전달합니다 .
여러 유형 매개 변수
제네릭 형식은 둘 이상의 형식 매개 변수를 가질 수 있습니다. 유형 매개 변수는 공분산 및 반공 변성의 동작을 변경하지 않으며 아래와 같이 여러 유형 매개 변수가 함께 발생할 수 있습니다.
제네릭 인터페이스 java.util.Map<K, V>
는 여러 유형 매개 변수의 예제로 자주 사용됩니다. 인터페이스에는 두 개의 유형 매개 변수 (키와 값에 각각 하나씩)가 있습니다. 객체를 키와 연관시키는 것이 유용합니다. 예를 들어, 객체를 더 쉽게 찾을 수 있습니다. 전화 번호부는 Map
여러 유형 매개 변수를 사용 하는 객체 의 예입니다 . 가입자 이름이 키이고 전화 번호가 값입니다.
인터페이스의 구현 java.util.HashMap
에는 임의의 Map
객체를 연관 테이블로 변환하기위한 생성자가 있습니다.
공분산으로 인해이 경우 매개 변수 개체의 형식 매개 변수는 정확한 형식 매개 변수 클래스 K
및 에 해당하지 않아도 V
됩니다. 대신 공분산을 통해 적용 할 수 있습니다.
여기서는 Id
의 수퍼 유형이고 CustomerNumber
,의 Person
수퍼 유형입니다 Customer
.
방법의 차이
우리는 유형의 차이에 대해 이야기했습니다. 이제는 좀 더 쉬운 주제로 넘어 갑시다.
'DevOps' 카테고리의 다른 글
Java 101 : 필수 Java 언어 기능 둘러보기, 1 부-1장 assertions and generics (0) | 2017.06.14 |
---|---|
Java의 유형 종속성, 2-3 (Collections API, 제네릭, 람다식 활용) (0) | 2017.06.14 |
Java의 유형 종속성, 2-2 (Collections API, 제네릭, 람다식 활용) (0) | 2017.06.14 |
Java에서 유형 종속성, Part 1-2 (array, generic, wildcard) (0) | 2017.06.14 |
Java에서 유형 종속성, Part 1-1 (array, generic, wildcard) (0) | 2017.06.14 |
Memcached를 이용한 php - 설치와 예제 (0) | 2014.03.07 |
Html Css @media quary for Smart phones (0) | 2011.04.16 |