Wpis z mikrobloga

Przypomniał mi się taki kruczek w Javie, że jeżeli zabraknie jakiegoś parametru typu jakoś w klasie (nie pamiętam czy tworzenie instancji jako surowy bez <> czy np. wywołanie jakiejś metody statycznej czy coś), to ogólnie "cała klasa" przechodzi/czy jest tworzona w "trybie surowym", co powoduje że parametr typu w innym miejscu (nie pamiętam gdzie, może w klasie wewnętrznej tej klasy?) też całkowicie traci znaczenie, co jest dość zaskakujące i prowadzi do niespodziewanego błędu.

Coś w rodzaju, że mamy Klasa a ona gdzieś tam w środku ma (nie pamiętam czy w metodzie czy klasie wewnętrznej, czy gdzie) inny parametr np. , to jeżeli stworzymy jej instancję bez określenia T (na surowo) to o dziwo też nie będzie można skorzystać z "tego czegoś" co miało - również będzie surowe.

Kojarzy ktoś na czym to dokładniej polegało? nie umiem teraz znaleźć przykładu ani artkułu żadnego, a przydałby mi się.

#programowanie #java
  • 12
@Eoghan: @EssePL: Niestety ani jedno, ani drugie. Kluczowe tu jest to, że mamy dwa różne parametry typu np. T i E.

Nasza klasa jest np. Klasa a gdzieś tam w jej wnętrzu jest coś z . Teoretycznei mamy dwa zupełnie różne niepowiązane paramtry trypu, ale jednak tworząc klasę surowo, tracimy całkowicie "generyczność" dotyczącą , czyli tak jakby cała klasa przechodzi "w tryb surowy".

Jednak właśnie dokładnie nie pamiętam jak to
@Eoghan: @EssePL: Już mi się przypomniało - jednak nie były to dwa nieokreślone parametry typu a konkretny parametr typu.

Jak zrobimy np. MojaKlasa implements Collection {....

Napiszemy sobie ładnie funkcje implementowanie z kolekcji, iterator() zwracający Iterator itd., to potem możemy się nadziać bo jak utworzymy naszą klasę:

MojaKlasa x = new MojaKlasa();

(czyli na surowo), to x.iterator() nie zwróci nam Iterator tylko surowego iteratora. Czyli przepada zarówno nasze jak i
@Eoghan: Dla mnie średnio logiczne, bo skoro nie podaje to czemu JVM ma nie wiedzieć, że klasa i tak implemetuje Collection tylko nagle sobie przyjmuje, że po prostu surowy Collection. Jedna z rzeczy, która chyba najbardziej zaskoczyła mnie w Javie.
@hbpitero: no na mój gust to co napisałeś, czyli, że:

Czyli przepada zarówno nasze <T> jak i wpisane na sztywno <String> - taki jakby "tryb raw" dla całej klasy.

i z drugiego komentarza

tylko nagle sobie przyjmuje, że po prostu surowy Collection

no właśnie nie. Typ klasy generycznej jest dziedziczony z rodzica, więc w Twoim przykładzie:

MojaKlasa implements Collection {
Przy wymazywaniu typu implementowany Collection ma podstawiany typ String w argumentach,
Pobierz Eoghan - @hbpitero: no na mój gust to co napisałeś, czyli, że:

Czyli przepada zarówn...
źródło: comment_okAx9MkcXgwK6mUlxxaU5TgtILFt934D.jpg
@Eoghan:

MojaKlasa<T> implements Collection<String> {


Przy wymazywaniu typu implementowany Collection ma podstawiany typ String w argumentach, więc MojaKlasa też > musi korzystać ze String lub podtypu Stringa co wynika z dziedziczenia

Nie jest tak jak mówisz, tutaj dziedziczenie nie ma nic do rzeczy i nic mi nie broni korzystać sobie z T do woli, wymazaniem "siebie" będzie MojaKlasa a wymazaniem rodzia będzie Collection. Dlatego spokojnie mogę stworzyć obiekt:

new MojaKlasa();

Wtedy
shiiit, ale mi namieszałeś w głowie tym przykładem, a jeszcze bardziej sam sobie namieszałem :)

Co do eclipse to bardziej o inną kwestię chodzi - powieloną metodę add() dla Object i typu parametru tak jakby przesłonięcie w tym momencie nie działało. Jak tak teraz na to spojrzałem to właśnie kwestia Bridge Method z linka, którego wkleiłem. Wszystko się składa w całość :d
to x.iterator() nie zwróci nam Iterator<String> tylko surowego iteratora.


@hbpitero: Po prostu tak działa wolny ryn... ee tzn. "type erasure" w Javie. W czasie kompilacji typy generyczne są "wymazywane" i dlatego x.iterator() zwróci Ci w runtime typ "raw", a nie generyczny.

Więc jeśli dobrze rozumiem problem, te linki powinny rozjaśnić to trochę bardziej:

http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java

http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens

+ http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

W razie czego pytaj.
@BeSmarter: Nie chodzi mi o erasure, ja mam na myśli przejście w "tryb raw" jeszcze przed kompilacją, a nie przez erasure. Oczywiście w każdym przypadku podczas runtime iterator będzie surowy, ale z genericsem z automatu zostanie dodane rzutowanie. To o czym mówiłem, to to, że gdy mam deklarację klasy:

class MojaKlasa extends Iterable { ....

i stworzą sobie dwa obiekty tej klasy:

MojaKlasa a = new MojaKlasa<>();

MojaKlasa b = new