Type dependency in Java, Part 1-2
Covariance and contravariance for array types, generic types, and the wildcard element
원문 : http://www.javaworld.com/article/3172592/java-language/type-dependency-in-java-part-1.html?page=2
Java의 제네릭 형식은 암시 적으로 불변이지만 일부 변수는 공 변하게 사용할 수 있습니다. 이는 ?
실제 유형 매개 변수로 사용할 수 있는 와일드 카드 ( ) 로 정의해야합니다 . Generic<?>
제네릭 형식의 모든 인스턴스화에 대한 추상 수퍼 유형이므로 모든 인스턴스화는 Generic
다음 Generic<?>
과 같이 호환됩니다 .
와일드 카드 유형은 추상 형식이므로 참조 용으로 만 사용할 수 있고 객체 용이 아닌 new Generic<?>()
컴파일러에서 거부 할 수 있습니다.
와일드 카드의 사용 예는 해당 요소 유형과 상관없이 컬렉션 또는 배열을 조작하는 메소드의 매개 변수입니다. 공분산은 배열에 대해 다음과 같은 메소드를 작성하기 쉽도록 만듭니다.
이 메소드는 모든 유형이 Object
배열 유형의 공분산과 호환되기 때문에 임의의 배열에 대해 호출 될 수 있습니다 .
이 메소드의 제네릭 버전은 호출이 호환성을 사용하지 않고 컴파일러에서 확인할 수있는 일반 인스턴스화를 사용하므로보다 안전합니다.
두 스왑 정의는 구별 가능한 서명이 없기 때문에 동일한 클래스에서 함께 발생하지 않을 수 있습니다.
이러한 솔루션 ArrayList
은 제네릭 형식에 대한 불변성 규칙 때문에 작동하지 않습니다. 와일드 카드는 공분산에 영향을주기 때문에 해결 방법으로 사용할 수 있습니다.
와일드 카드 버전 호출은 임의의 요소 유형으로 가능합니다.
우리는 어떤 타입이나 슈퍼 타입이 공분산을 가능하게하는지 명시하지 않았기 때문에 그런 호환성을 불특정의 공분산 이라고 부릅니다 . 그것은 한 번에 두 가지 수준에서 발생하는 지정되지 않은 공분산에 따라 호환성에 대한 가능성 : 일반적인 유형 (의 수준 ArrayList
에 List
) 및 요소의 수준 ( Integer
에 ?
) :
제네릭 형식에 대한 명시 적 공분산
광 공분산 이전 섹션에 도시 된 일반화 될 수있다. 경우 Generic<SubType>
에 호환했다 Generic<SuperType>
, 종류는 암시 적으로 공변 될 것이다. 와일드 카드를 바인딩 하면 extends
형식이 명시 적 Generic<SubType>
으로 공변 (covariant)하게 Generic<? extends SuperType>
됩니다. 이 와일드 카드 유형 의 참조를 선언 할 수 있습니다 (모든 와일드 카드 유형은 추상이기 때문에 객체가 아닙니다).
이 참조 Generic
는 다음의 하위 유형의 실제 유형 매개 변수가있는 인스턴스를 참조 할 수 있습니다 SuperType
.
이것은 유형이 ( 위에서 설명한 것처럼 모든 유형 의 모든 인스턴스화의 추상적 인 상위 유형과 마찬가지로) 유형이 하위 유형이있는 Generic<? extends SuperType>
모든 인스턴스화의 추상 상위 유형임을 의미합니다 .Generic
SuperType
Generic<?>
Generic
바인딩에 와일드 카드를 사용하는 것은 type 매개 변수에 특정 속성이 필요한 경우에 필요합니다. 예를 들어 매개 변수 컬렉션의 요소를 조작하려는 경우입니다.
첫 번째 메서드는 Number[]
배열 사이의 공분산의 결과로 매개 변수를 사용하여 호출 할 수 있습니다 .
두 번째 방법은 모든 호출 할 수 ArrayList
A의 파라미터 Number
와일드와 공분산의 결과로서 실체화 :
위의 코드 싹둑, 우리는 다시 두 가지 수준에서 호환성을 사용하고 있는지 참고 : 매개 변수화가 ArrayList<T>
의 하위 유형 Collection<T>
과 Integer
의 하위 유형입니다 Number
.
유형 매개 변수의 변수에 액세스하는 공변량
앞의 몇 가지 예에서 경계 유형의 와일드 카드를 사용하여 제네릭 유형 간의 명시 적 공분산을 확인할 수 있습니다. 이 공분산은 형식 매개 변수의 변수에서 작동하지만 일반 클래스의 메서드 매개 변수에서는 항상 작동하지 않습니다.
클래스에서 Generic
우리 T
는 메서드의 (입력 및 출력) 매개 변수의 형식으로 type 매개 변수 를 사용 한다고 가정합니다 .
이 경우 메서드 write()
를 직접 호출 할 수 없습니다 wildcardReference
(형식 캐스팅 후에 만 호출 할 수 있음).
와일드 카드는 유형이 아니기 때문에 호환되지 않는 유형이 Object
있습니다. 그러나 와일드 카드 자체는 호환 가능합니다 Object
(다른 유형에는 호환 되지 않습니다). 함수의 타입 파라미터 결과는 참조에 의해 참조 될 수 있습니다 Object
:
이 규칙은 바운드 와일드 카드 유형에 적용됩니다. 입력 매개 변수는 직접 전달할 수 없습니다. 캐스팅 후에 만 통과 할 수 있습니다. 출력 매개 변수는 바인딩의 유형 (또는 수퍼 유형) 변수에 지정할 수 있습니다.
마지막 두 프로그램 행의 유형 변환은 ClassCastException
(언제나처럼) 던져 버릴 수 있으므로 안전하지 않습니다. 발생 여부는 마지막에있는 객체의 유형에 따라 달라집니다 write()
. new SubType()
위의 시퀀스와 마찬가지로 예외가 발생하지 않습니다. 마지막 두 라인 사이의 차이점은 첫 번째의 참조 (변환되고 있다는 것이다 Generic<? extends SuperType>
에 Generic<SubType>
), 그리고 read()
두 번째로하면서, 호출의 결과 read()
(변환한다 ?
으로 SubType
첫번째이다 그래서) (약간 ) 안전한.
우리는이 안 바운드 와일드 카드에 의해 제한되는 것을 의미하는 것으로 해석 할 수 있습니다 Object
: Generic<?>
같은이 (거의) 동일한 효과를 . 따라서, 불분명 한 공분산은 호환성을 통한 명백한 공분산이라고 말할 수있다 . Generic<? extends
Object
>Object
이러한 규칙은 매개 변수뿐 아니라 형식 매개 변수 유형의 변수에 대한 모든 읽기 또는 쓰기 액세스 (공개 또는 액세스 가능한 것으로 가정)에 유효합니다. 어떤 유형도 상위 경계와 호환 ?
되지만 ?
호환 될 수 Object
없습니다 (경우에 따라 다른 유형으로 는 변환 할 수 없음).
매개 변수화 된 유형에 대한 반 공분산
Recall that contravariance means downwards compatibility. Arrays are explicitly contravariant; syntactically this can be expressed through type conversion (via casting, see above):
Among different instantiations of a generic type, the compiler rejects type conversion. But generic types are explicitly contravariant, too. Syntactically this can be expressed through a lower bound of the wildcard with super:
This variable can refer any instantiation of Generic
with any supertype (e.g., an Object
) of SubType
:
Here, the assignment of the SuperType
instantiation takes place downwards, namely to the SubType
instantiation contravariantReference
--this means contravariance.
상한은 읽기와 쓰기에 대한 행동을 변경하기 때문에 (앞 절에서 논의했듯이), 반공으로 Object
둘 다 가능해진다.
? super
다른 유형들과 같은 반동 ( ) 은 공분산 ( )과 String
비교하여 읽기와 쓰기의 방향을 바꾼다 ? extends
:
그 이유는 하한 (여기 String
)이 와일드 카드와 호환 가능하지만 그 반대도 마찬가지이기 때문입니다. 이 사이의 차이 contravariantO.read() (OK)
와 contravariantS.read() (error)
: ?
호환됩니다 Object
에 있지만 String
.
1 부 결론
Java 유형은 내재적으로 또는 명시 적으로 서로 호환 될 수 있습니다. 런타임시 예외를 피하기 위해 명시 적 호환성이 프로그래머에 의해 주장되어야하지만 암시 적 호환성은 컴파일러에 의해 선언됩니다. 종속 (배열 및 일반) 유형도 호환 될 수 있습니다. 상위 호환성 (공분산이라고 함)은 주로 내재적 인 반면 하위 호환성 (반공립)은 배열 유형에 대해 명시 적입니다.
Java는 제네릭 형식에 암시 적 분산을 허용하지 않습니다. 그렇게하면 형식 안전성이 위협 받기 때문입니다. 와일드 카드는 (암시 적으로) 지정되지 않은 공분산을 허용하는 절충안입니다. 제네릭 형식에 대한 공분산 및 반항은 명시 할 수 있습니다. 개발자는 표 1과 같이 상한 및 하한을 정의해야합니다.
Java 표준 라이브러리의 최신 버전에서 발견되는 많은 물음표 (와일드 카드) 및 박스 일반에 대해 궁금해하신 분이라면이 기사의 제 2 부가 도움이 될 것입니다. 여러 API 예제에서 반공 변성을 살펴보고 컴파일러가 일반 유형의 변수에 액세스하지 못하는 이유를 설명합니다. 제네릭 형식의 개체를 만드는 방법과 분산 아이디어를 메서드 선언, 정의 및 호출로 전송하는 방법을 배우게됩니다. 우리는 람다의 호환성과 편차에 대해 간략하게 살펴볼 것입니다 - 프로그래밍 언어 애호가들에게 흥미로운 일반적인 람다 표현식을 포함합니다.
'DevOps' 카테고리의 다른 글
Java의 유형 종속성, 2-3 (Collections API, 제네릭, 람다식 활용) (0) | 2017.06.14 |
---|---|
Java의 유형 종속성, 2-2 (Collections API, 제네릭, 람다식 활용) (0) | 2017.06.14 |
Java의 유형 종속성, 2-1 (Collections API, 제네릭, 람다식 활용) (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 |
Python + Django + Oracle (0) | 2009.11.12 |