>Java >java지도 시간 >Java의 제네릭 공분산

Java의 제네릭 공분산

高洛峰
高洛峰원래의
2016-11-22 17:56:441491검색

작업 중 문제가 발생했습니다. 코드에 다음과 같이 설명되어 있습니다.

package test;import java.util.LinkedList;
import java.util.List;public class ListTest {
    public void func(List<Base> list) {
    }
    public static void main(String args[]) {
        ListTest lt = new ListTest();
        List<Derived> list = new LinkedList<Derived>();
        lt.func(list); // 编译报错    }
}class Base {
}class Derived extends Base {
}

여기서 Base 목록을 매개변수로 사용할 수 있는 func 함수를 작성해야 합니다. Derived는 Base의 파생 클래스이므로 Derived의 목록도 Base의 목록의 파생 클래스여야 하기 때문에 Derived 목록을 전달해도 괜찮을 것이라고 생각했는데 컴파일러에서 오류를 보고했습니다.

이유는 인터넷에서 몇 가지 정보를 확인했기 때문입니다. Java의 제네릭은 공변적이지 않습니다.

제네릭의 공변성과 반공변성은 둘 다 용어입니다. 전자는 원래 지정된 파생 유형보다 덜 파생된(덜 구체적인) 유형을 사용하는 능력을 나타내고 후자는 원래 지정된 유형보다 덜 파생된 유형입니다. 파생 유형은 더 파생된(더 구체적인) 유형입니다.

예를 들어 C#의 제네릭은 공분산을 지원합니다.

IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;

그러나 Java의 제네릭은 공분산을 지원하지 않습니다. 위와 유사한 코드는 Java에서 컴파일할 수 없습니다.

그러나 흥미로운 점은 Java의 배열이 공분산을 지원한다는 것입니다. 예를 들면 다음과 같습니다.

Integer[] intArray = new Integer[10]; 
Number[] numberArray = intArray;

요약: Java의 제네릭은 유형 안전 관점에서 공분산을 지원하지 않습니다. 예를 들어 C#에서는 이 디자인을 사용하지 않습니다. Java 설계자는 사용 편의성과 유형 안전성 중에서 선택했다고 말할 수 있습니다.

마지막으로 원래 질문으로 돌아가서 func 메소드를 구현하려면

public void func(List list) {
}

으로 수정하거나 매개변수화된 유형을 사용할 수 있습니다.

public <T> void func(List<T> list) {
}

하지만 이것도 문제가 있습니다. func의 매개변수 유형이 흐릿해집니다. 더 좋은 방법은 func를 변경하는 것이 아니라 매개변수를 전달할 때 기본 유형 목록을 전달하는 것입니다. 이를 위해서는 요소를 목록에 추가할 때 요소를 기본 유형으로 변환해야 합니다.

PS: 매개변수 유형 제한:

public void func(List<? extends Base> list) {
}


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.