2011-11-14 9 views
9

Mam jakiś kod wiążący Guice, używając generycznych, które kompilują i działają dobrze od kompilatora Eclipse, ale nie z kompilatora Java (wiersza poleceń). Zaktualizowałem do najnowszego (1.7.0_01) pakietu Java SDK, ale nadal pojawia się następujący błąd.Błąd generowania języka Java: typy niewłączalne z kompilatora wiersza komend

[error] ...\BindCategorySelectorActivity.java:42: error: inconvertible types 
[error]         (Class<? extends ListAdapterDataProvider<Row<? extends DatabaseItem>>>) CategoryDataProvider.class); 
[error]                               ^
[error] required: Class<? extends ListAdapterDataProvider<Row<? extends DatabaseItem>>> 
[error] found: Class<CategoryDataProvider> 
[error] 1 error 
[error] {file:/.../compile:compile: javac returned nonzero exit code 

odpowiedni kod:

public interface Category extends DatabaseItem {} 
public class CategoryDataProvider implements 
ListAdapterDataProvider<Row<Category>> {} 
public class BindListViewHandlerWithSpecificProvider extends AbstractModule { 
    public BindListViewHandlerWithSpecificProvider(
    Class<? extends ListAdapterDataProvider<Row<? extends DatabaseItem>>> 
     dataProviderClass) {} 
} 

@SuppressWarnings("unchecked") 
// Error happens here: 
final BindListViewHandlerWithSpecificProvider 
bindListViewHandlerWithSpecificProvider = 
    new BindListViewHandlerWithSpecificProvider(
    (Class<? extends ListAdapterDataProvider<Row<? extends DatabaseItem>>>) 
    CategoryDataProvider.class); 

Odpowiedz

6

Zrób sobie przysługę i zrobić uskok po którym następuje przygnębiony:

Class<...> foo = (Class<...>)(Object)MyClass.class; 

Problem jest, że CDP.class jest typu Class<CDP>, CDP bycia typ surowy. Chociaż sparametryzowany typ C<T1,...,Tn> jest podtypem typu surowego C (§4.10.2), odwrotność nie jest prawdą: C nie jest podtypem C<T1,...,Tn>. Wydaje się to być prawdą tylko z powodu niezaznaczonej konwersji (§5.1.9). To powoduje problem: oczekujesz, że CDP "rozszerzy się" (jak w górnej granicy Class<? extends ...>) LADP<Row<? extends DI>>. Nie dzieje się tak dlatego, że ograniczanie argumentów typu (§ 4.5.1.1) jest zdefiniowane w stosunku do podtypów i nie uwzględnia konwersji niezaznaczonych.

(Lub do sedna: javac ma ten jeden w prawo.)

+0

Cóż, udało się skompilować, ale nie jestem pewien, czy dodanie dodatkowej obsady do obiektu po prostu maskowało problem. Guice zawiesza się przy wyjątku wskaźnika pustego przy próbie wiązania. Linia, której raportuje, uzyskuje dostęp do 'bindListViewHandlerWithSpecificProvider'. Pamiętaj, że ten identyczny kod kompiluje się i wykonuje bezbłędnie, gdy jest zbudowany w środowisku Eclipse. –

+1

Przyznam, że to dziwne zachowanie. Wykonanie dodatkowej obsady w Object nie powoduje niczego poza wyłudzeniem javaca z 'sideCast'ing. Powinieneś skończyć skutecznie tym samym programem. –

+0

Czy znasz obsługę Genika dla generycznych i czy istnieje lepszy mechanizm do przekazywania sparametryzowanych typów? Każdy pomysł, czy Scala zapewnia lepszą obsługę przekazywania parametrów sparametryzowanych? –

1

znam odpowiedź pracuje i akceptowane, ale wierzę, że przygnębiony nie jest idealnym rozwiązaniem. Również moje czyszczenie kodu usunąć przestarzałe rzucanie ...

1) przyczyną Zaćmienie i linii poleceń nie powoduje tego samego problemu jest z powodu ustawień zaćmienia. Przejdź do preferencji - java - kompilator - Błędy/Ostrzeżenia i ustaw Typy ogólne (niezaznaczone operacje typu ogólnego) do ostrzeżenia. Jeśli wykryjesz ten sam problem, wykryjesz ten sam problem, jeśli usuniesz ten sam problem, a znajomy pokaże mi inne rozwiązanie. Aby rozwiązać ten kod poprawnie (bez zrzucony) wystarczy zmienić CategoryDataProvider.class do tego:

new CategoryDataProvider<Row<DatabaseItem>>().getClass() 

Następnie umieścić z powrotem @SuppressWarnings("unchecked")

+0

Ta metoda może działać tylko wtedy, gdy klasa (w tym przypadku CategoryDataProvider) ma domyślny konstruktor. W bardziej skomplikowanych przypadkach ta metoda może wymagać wykonania wielu przygotowań i inicjalizacji, aby odzyskać klasę. –