2014-04-22 15 views
5

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>?

Odpowiedz

5

Ponieważ użyto surowego Test, wszystkie leki generyczne w klasie Test skutecznie wpisać-skasowane, nawet niespokrewnionych rodzajowych, takich jak powrót Set<Integer>, tak że Set<Integer> zwrócony przez getInts staje się po prostu surowy Set. To wyjaśnia, dlaczego masz niezgodne typy, ponieważ surowy Set zwróci Object s, a nie Integer s.

Section 4.8 of the JLS obejmuje nieprzetworzone typy:

typ konstruktor (§8.8) sposobu, przykładowo (§8.4, §9.4) lub pola nie statyczny (§8.3) M typu C surowego która nie jest odziedziczone nadrzędnych lub superinterfaces jest surowy typu, który odpowiada usunięciem typu w ogólnym deklarację odpowiadającą C

i

Używanie typów surowych jest dozwolone tylko jako koncesja na zgodność starego kodu. Użycie surowych typów w kodzie napisanym po wprowadzeniu generycznych do języka programowania Java jest zdecydowanie odradzane. Możliwe, że przyszłe wersje języka programowania Java uniemożliwią stosowanie typów surowych.

(Kopalnia nacisk)

Powodem takiego zachowania jest dla wstecznej kompatybilności z kodem pre-rodzajowych Java, ponieważ wersje pre-generyków wbudowanych klas Javy są takie same rzeczy jak surowego typu wersje uogólnionych wbudowanych klas. Oznacza to, że pre-generics Set to to samo, co surowe Set (usunięto generyczne).

0

Tak, podczas deklarowania zmiennej jako typu surowego (lub gdy wyrażenie ma postać odniesienia typu surowego), wszystkie interakcje z tym odniesieniem zachowują się tak, jakby wszystkie typy ogólne zostały usunięte. Obejmuje to ogólne typy list parametrów i typy zwracanych.

Powiązane problemy