형 변환에 대해 파고들면 Covariant, Contravariant, Invariant과 같은 용어들을 쉽게 만날 수 있다.
세 용어 모두 형 변환에 있어 슈퍼타입-서브타입 관계성을 정의한다.
A와 B를 타입, f를 형 변환, 그리고 <=을 서브타입 관계성이라 가정하자. (즉, A<=B는 A가 B의 서브타입을 의미한다)
A<=B일 때 f(A) <= f(B)면 CovariantA<=B일 때 f(B) <= f(A)면 Contravariantf(A) = List<A>로 다시 확인해보자
List<String>이 List<Object>의 서브타입임을 의미한다.List<Object>이 List<String>의 서브타입임을 의미한다.List<String>와 List<Object>는 서로 변환되지 않는, String과 Object간 서브 타입 관계성이 사라짐을 의미한다. Java에서f(A) = A[]는 Covariant하다. 즉, String[]은 Object[]의 서브타입에 해당한다.
Java에서는 List<String>과 List<Object>는 Invariant하다. Generics 자체가 invariant로 인정되는 경우가 많다.
또 예를 들자면, Integer는 Number의 서브 타입이지만, List<Integer>는 List<Number>의 서브 타입이 아니다. 이 둘의 공통 부모는 List<?> 뿐이다.

출처: 오라클 공식 문서
그래서 Invariant 관계에 놓인 이 두 리스트에 대해 관계성을 형성하기 위해서는 와일드카드를 사용해야 한다.
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numList = intList;
List<? extends Number> numList는 Number의 서브타입 (Integer도 해당)의 리스트를 모두 허용하기 때문에 numList에 intList를 지정할 수 있다.
https://stackoverflow.com/questions/8481301/covariance-invariance-and-contravariance-explained-in-plain-english
https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html