Jeśli zadeklarujesz wystąpienie klasy ogólnej jako surowego typu w Javie, czy kompilator przyjmie sparametryzowany typ Object
dla wszystkich metod należących do klasy? Czy to sięga nawet do tych metod, które zwracają pewną postać (np. Collection
) konkretnego typu sparametryzowanego?Java - zachowanie klasy członków klas ogólnych
Błędnie zadeklarowałem instancję klasy ogólnej bez parametru sparametryzowanego, co doprowadziło do bardzo interesujących efektów końcowych. Podałem uproszczony przykład scenariusza, który spowodował błąd kompilacji "niekompatybilnych typów". Moje podstawowe pytanie: Dlaczego javac generuje błąd "niekompatybilnych typów", narzekając na wskazaną linię poniżej?
import java.util.*;
public class Main {
public static void main(String[] args) {
final Test<String> t1 = new Test<String>();
final Test t2 = new Test<String>();
for (final Integer i : t1.getInts()) {
System.out.println(i);
}
for (final Integer i : t2.getInts()) { //<-- compile-time error
System.out.println(i);
}
}
public static class Test<T> {
public Test() {
}
public Set<Integer> getInts() {
final Set<Integer> outSet = new HashSet<Integer>();
outSet.add(new Integer(1));
outSet.add(new Integer(2));
outSet.add(new Integer(3));
return outSet;
}
}
}
Interesująca uwaga jest taka, że jeśli t2
jest zadeklarowana z typem wieloznacznego (Test<?> t2…
) kod kompiluje i działa zgodnie z oczekiwaniami.
Użycie pętli for wywołuje next()
w iteratorze na zestawie zwróconym przez getInts()
(który zwraca typ ogólny pobierany z Iterable będącego iteracją). The documentation here wspomina, że jeśli Iterowalna jest nieprzetworzona, jako typ powrotu używany jest Object
. Dlaczego wygląda na to, że kompilator zmienia także typ zwrotu z Test.getInts()
z Set<Integer>
na Set<Object>
?