2013-03-15 17 views
6

Szukałem odpowiedzi na to, ale bezskutecznie. Moje pytanie brzmi: dlaczego nie można spuścić z lekami generycznymi. Mam klasy o nazwie Praca i rozszerza klasę o nazwie modeluNie można obniżyć przy użyciu klasy List w Javie

Job extends Model 

Teraz mam zbiór zadań z kodem wielokrotnego użytku, który generuje listę modeli

// error: Cannot cast from List<Model> to List<Job> 
List<Job> jobs = (List<Job>) jobMapper.fetchAll(); 

gdzie jobMapper.fetchAll() zwraca Lista, w której każdy model wewnątrz niej jest obiektem Job.

Sądziłem, to będzie działać, bo mogę zrobić:

EditText mUsername = (EditText) findViewById(R.id.editUserName); 

który jest prosty rzutowanie w dół.

+0

możliwe duplikat [Jak rzucisz listę obiektów z jednego typu do drugiego w Java?] (Http://stackoverflow.com/questions/933447/how-do-you-cast-a- list-of-objects-from-one-type-to-another-in-java) – artbristol

+0

Zadanie jest podklasą modelu, zadanie [] jest podklasą modelu [], ale lista nie jest podklasą listy . – StarPinkER

+0

@JermaineXu: "podtyp" jest bardziej poprawny niż "podklasa" tutaj. Ponieważ 'List ' nie jest tak naprawdę klasą, ale typem. (A ty możesz * twierdzić, że 'Job []' nie jest również klasą). –

Odpowiedz

10

Nie możesz tego zrobić, ponieważ Java nie pozwala na to. Read this. Należy rade:

List<Job> jobs = (List<Job>) ((List<?>)jobMapper.fetchAll()); 
+0

Świetnie! To wystarczyło. Podczas gdy dostaję niezapisane ostrzeżenie, mogę z tym żyć, ponieważ jestem prawie pewien, że rzucane są wartości. Dzięki za pomoc. Doceń to bardzo! – Strategist

+2

Przy okazji: to całkiem niezły pomysł *. Ukrywa tylko ostrzeżenie i skutecznie usuwa z tej listy wszystkie ogólne informacje o typie (i wszystkie gwarancje, które otrzymujesz z generycznych). –

+0

@ Joachim jest lepszy sposób to zrobić? czy możesz opublikować odpowiedź. dzięki – Strategist

2

można wykonać następujące czynności:

List<Job> jobs = (List) (jobMapper.fetchAll()); 

(I tłumić ostrzeżenie jeśli jesteś przekonany, że to bezpieczne w przypadku)

The kompilator nie zezwala na rzutowanie, którego próbujesz, ponieważ gdy masz już listę Lista < Zadanie> i listę Model <> wskazując tę ​​samą listę, możesz dodać do niej instancje modelu i utworzyć listę < Zadanie> zawiera element modelu, który łamie bezpieczeństwo typu.

W związku z tym należy zachować ostrożność przy dopuszczaniu tego rodzaju sztuczek - może on wrócić do ciebie później w postaci wyjątku ClassCastException, w którym nie spodziewasz się, że wystąpi.

Odnośnie ostatniego pytania: Należy pamiętać, że podczas pracy jest modelu i Pracy [] jest model [], to nie jest prawdziwe w odniesieniu do zbiorów: lista < Praca>nie List < typu>. To trochę zaskakujące, ale wynika to z moich wyjaśnień powyżej. Zniszczyłoby to bezpieczeństwo typu, aby umożliwić tę obsadę bez ostrzeżenia/błędu.

+0

To również działa z ostrzeżeniem. – Strategist

+0

Przepraszam za drugi komentarz opublikowany w niewłaściwym polu – Strategist

0
List<Job> jobs = jobMapper.fetchAll(); 

Jest źle, nigdy nie jest jawna lista zadań.

Zastosowanie

List<? super Job> jobs = jobMapper.fetchAll(); 

zamiast.

+0

Pozwala to tylko na powtarzanie zadań jako obiektów (i przesyłanie ich do zadania). –

+0

Ponieważ nigdy nie jest jawna lista ob Jobs. : D –

+0

Przykro mi, ale to nie działa dla mnie. Podczas gdy linia wydaje tylko ostrzeżenie. Nie mogę już używać zmiennej zadań, ponieważ używam jej w adapterze tablicowym ArrayAdapter i nie można już dodawać tej kolekcji do adaptera, ponieważ nie jest już rozpoznawana jako lista Strategist

0

Jest niedozwolone, ponieważ może/może prowadzić do błędów w czasie wykonywania. Co się stanie, jeśli lista zawiera już obiekty nie należące do klasy Job?

Powinieneś albo:

  1. Zmień jobMapper.fetchAll() wrócić List<Job>.

  2. Rzuć obiekt zamiast listy, np.Job job = (Job) jobs.get(0).

+0

W podobny sposób obsada View to EditText w przykładzie findViewById() może prowadzić do RuntimeExceptions .., ale jest jednak dozwolone. – baske

+0

Nie mogę uczynić jobMapper.fetchAll(), aby zwrócić listę , ponieważ fetchAll jest metodą klasy bazowej, której używam ponownie. Robię również userMapper.fetchAll(), gdzie zwraca obiekt użytkownika (User extends Model). – Strategist

+0

@baske: rzutowanie na EditText rzuca obiekt. Musisz oczekiwać wyjątku ClassCastException, gdy wykonasz rzut tak. Ale podczas pobierania obiektu z ogólnego kontenera nie oddajesz elementu, który został zwrócony, a więc nigdy nie uzyskasz wyjątku ClassCastException (chyba że rzucisz swoją kolekcję i zignorujesz wszystkie ostrzeżenia - patrz komentarz Joachima Sauera do rozwiązania autorstwa Leonidasa). – Axel

Powiązane problemy