2015-06-24 21 views
6

Starałem się znaleźć odpowiedni tytuł dla tego pytania, ponieważ zaobserwowane przeze mnie zjawisko jest bardzo dziwne. W związku z tym pomijam wyjaśnienie mojego problemu dosłownie, a zamiast tego pokażę trochę (miejmy nadzieję) samoopisującego się kodu. Rozważmy następującą klasę parametryczne:Dlaczego program Eclipse Compiler traci parametr o ustalonym typie?

public class GenericOptional<T> { 

    public GenericOptional(T someValue) {} 

    public T getValue() { return null; } 

    public Optional<String> getOptionalString() { return Optional.empty(); } 
} 

Co chciałbym podkreślić to, że zwracany typ Optional<String> metody getOptionalString() nie zależy na typu parametruT.

teraz rzucić okiem na poniższy kod, który zostanie skompilowany wewnątrz Luna Eclipse 4.4.2 korzystając Java 8u45:

public static void main(String[] args) { 
    Object obj = new GenericOptional<>(Boolean.TRUE); 
    GenericOptional go = (GenericOptional) obj; 
    Optional os = go.getOptionalString(); 
} 

lokalna zmienna os ma typ Optional bez Typu parametrString! Kompilator Eclipse utracił informacje o ustalonym parametrze typu. Czy ktoś wie, dlaczego?

Spójrzmy teraz na drugim przykładzie kodu:

public static void main(String[] args) { 
    Object obj = new GenericOptional<>(Boolean.TRUE); 
    GenericOptional<?> go = (GenericOptional) obj; 
    Optional<String> os = go.getOptionalString(); 
} 

Deklarując zmienną lokalną go jak GenericOptional<?> zwracany typ metody getOptionalString() teraz jest Optional<String> jak oczekiwano.

Czy ktoś może wyjaśnić to zachowanie?

Odpowiedz

4

stoją zachowanie raw types. Kiedy używasz typu surowego, Generics są skutecznie wyłączane całkowicie, niezależnie od tego, czy istnieje połączenie między generyczną sygnaturą elementu a parametrem typu klasy.

Powodem tego jest to, że surowe typy są funkcją zapewniającą zgodność wsteczną tylko z kodem pre-Generic. Więc albo masz generics, albo nie.

Jeśli metoda Generic nie zależy od rzeczywistego parametru typu klasy, problem jest łatwy do ustalenia:

GenericOptional<?> go = (GenericOptional<?>) obj; 
Optional<String> os = go.getOptionalString(); 

Korzystanie <?> oznacza „nie wiem rzeczywisty parametr typu i I don nie obchodzi mnie, ale używam sprawdzania rodzaju ogólnego ".

+0

Dziękuję za odpowiedź. Kocko udzielił tej samej odpowiedzi i nie wiem, jak udzielić ci prawidłowej/najlepszej aprobaty. W związku z tym, że najpierw odpowiedziałeś na to pytanie, nawet jeśli nie podałeś przykładowego kodu, aby wesprzeć twoje wyjaśnienie, dam ci "najbardziej pomocną" aprobatę. Jeśli uważasz, że odpowiedź Kocko ma większą wartość dla osób, które chcą wiedzieć, jak to działa, pozwól mi nie, a ja przekażę Kocko "najbardziej pomocną" aprobatę. – Harmlezz

4

Nie chodzi o Eclipse ani nic, ale o surowe typy.

Spójrzmy na ten fragment:

public static void main(String[] args) { 
    Object obj = new GenericOptional<>(Boolean.TRUE); 
    GenericOptional go = (GenericOptional) obj; 
    Optional os = go.getOptionalString(); 
} 

Tutaj tworzysz surowy wystąpienie GenericOptional, co oznacza, że ​​informacje typu parametr zostanie całkowicie wyłączony. Więc uruchamianiu tego surowyGenericOptional oznacza, że ​​instancja narazi metod, jak następuje:

public class GenericOptional { 

    public GenericOptional(Object someValue) {} 

    public Object getValue() { return null; } 

    public Optional getOptionalString() { return Optional.empty(); } 
} 

Jednak jeśli teraz przeglądu drugi fragment

public static void main(String[] args) { 
    Object obj = new GenericOptional<>(Boolean.TRUE); 
    GenericOptional<?> go = (GenericOptional) obj; 
    Optional<String> os = go.getOptionalString(); 
} 

widzimy, że robisz ogólne wystąpienie GenericOptional. Nawet to wpisać parametr jest <?>, kompilator nie będzie wyłączania dbając o typu parametrów, więc instancja narazi metodę getOptionalString() parametryzowane, tak:

public Optional<String> getOptionalString() { return Optional.empty(); } 
+0

Dziękuję Kocko za miłe wyjaśnienie. Proszę zobaczyć komentarz, który dodałem do odpowiedzi Holgera, dlaczego zazwyczaj udzielałem mu "najbardziej pomocnej" aprobaty. Mam nadzieję, że wszystko w porządku z tą decyzją. – Harmlezz