문제

I have classes in advanced programming at my university and I have a little trouble understanding how this code works.

public final class GenericClass<T> {
    private void overloadedMethod(Collection<?> o) {
        System.out.println("Collection<?>");
    }

    private void overloadedMethod(List<Number> o) {
        System.out.println("List<Number>");
    }

    private void overloadedMethod(ArrayList<Integer> o) {
        System.out.println("ArrayList<Integer>");
    }

    public void method(List<T> l) {
        overloadedMethod(l);
    }

    public static void main(String[] args) {
        GenericClass<Integer> test = new GenericClass<Integer>();
        test.method(new ArrayList<Integer>());
    }
}

Why does this code print "Collection<?>"?

도움이 되었습니까?

해결책

The declaration of method(List<T> l) does not specify any bounds on the type T. There is no guarantee that T is Number or a subclass of Number. Therefore, the compiler can only decide that this method calls overloadedMethod(Collection<?> o).

Remember: after compilation, the information about generics is not available anymore in the class files.

다른 팁

Whenever you define a generic type, a corresponding raw type is automatically provided This method

public void method(List<T> l) {

}

is replacing with

public void method(List<Object> l) {

}

If You read about Wildcard types, You will see that List<Number> and List<Object> or ArrayList<Integer> and List<Object> hasn't any type relationship. List<Object> is a subtype of the Collecion<?> therefore this method is called.

when you deal with method overloading you must put three concepts in your mind:

  1. Widening
  2. Boxing
  3. Var_args

your problem lies in the first point which is widening, the java compiler gives priorities to each of these concepts the same order as they are listed above, so it prefers widening and when you call your method as test.method(new ArrayList<Integer>()); the compiler finds that ArrayList<Integer>() could be widened to Collection<?> and since it has the highest priority it calls these version and neglects the other ones Note: if you change the declaration of the other two methods to private void overloadedMethod(ArrayList<?> o) and private void overloadedMethod(List<?> o) the compiler will also call the Collection<?> version because it's the preferred one

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top