getClass() zwraca zaskakujący(przynajmniej mnie) wynik

0

Witam,

Załączam programik w którym jest klasa Klasa1 i jej rozszerzenie Klasa2, później robimy obiekt rozszerzonej klasy Klasa2 i rzutujemy na węższą Klasa1. W ten sposób uzyskujemy obiekt klasy Klasa1.

Teraz pytanie, czemu metoda getClass() zastosowana dla tego rzutu pokazuje: class Klasa2
a nie class Klasa1?

kod:

class Klasa1{
private int a=1;
}

class Klasa2 extends Klasa1{
private int b=2;
}

public class Test{
public static void main(String[] args){

Klasa2 k2=new Klasa2();
Klasa1 k1=(Klasa1)k2;

System.out.println(k1.getClass());
}

}

Mógłby mi ktoś to wytłumaczyć?
Pozdrawiam i czekam na odpowiedźi
Tomek

0

Dlatego, że obiekt jest instancją klasy Klasa2 - co w tym dziwnego?

0
Tompey napisał(a)

robimy obiekt rozszerzonej klasy Klasa2 i rzutujemy na węższą Klasa1. W ten sposób uzyskujemy obiekt klasy Klasa1.

Tu jest blad. Ty tylko przypisujesz Klasa2 do Klasa1, nic sie nie zmienia, a na pewno nie typ. Klasa2 jest obiektem Klasa1 od samego poczecia, jak i rowniez jest obiektem Klasa2.
Poczytaj o klasach, dziedziczeniu i polimirfizmie i powinno byc jasne.

0

w kodzie jest rzutowanie na Klasa1:
Klasa1 k1=(Klasa1)k2;
nie rozumiem czemu k1 nie jest instancją klasy Klasa1 ... przecież k1 zawiera int a=1, a nie zawiera int b=2 jakby było przy tworzeniu k w taki sposób: Klasa2 k=new Klasa2();

0
::. napisał(a)

Poczytaj o klasach, dziedziczeniu i polimirfizmie i powinno byc jasne.

czytam, czytam, będę czytał dalej... może się wyjaśni... ee trudne początki;)

0

Poniższy kawałek kodu musi zaalokować pamięć co najmniej na dwie zmienne a i b

        Klasa2 k2=new Klasa2();

do tej pamięci jednoznacznie mogą się tylko odwoływać obiekty Klasy1 i Klasy2. Inne (szersze) typy klas powodowałyby odczyty spoza zaalokowanej pamięci - Eclipse np tego pilnuje choć czasami mu umyka i reszta jest sprawdzana w runtimie i strzela java.lang.ClassCastException np:

	Klasa1 a1 = new Klasa1();
	Klasa2 a2 = (Klasa2)a1;

Pomyśl jaki mess powstałby jakbyś rzutował Klasa1 na Klasa2. Stąd wydaje się naturalnym aby obszar pamięci był znakowany ostatnią z klas pochodnych w łacńcuchu dziedziczenia (oczywiście poniżej tej której instancję własnie tworzymy) - tak aby potem możliwe było rozpoznanie w runtime możliwości ponownego rzutowania z Klasa1 na Klasa2, czyli coś takiego:

        Klasa2 k2=new Klasa2();
        Klasa1 k1=(Klasa1)k2;
        Klasa2 k3=(Klasa2)k1;
0

Co ma do tego Eclipse to ja nie wiem. Po prostu takie rzytowanie jest 100% poprawne, mimo ze czasami daje wlasnie taki wyjatek.

0

Eclipse pewnie nic, ale akurat jego używam. Powinienem napisać że nie jest wykrywany na poziomie kompilacji. Ludzie już tak maja że opisują to co widzą :D.

Co do poprawności rzutowania to moim zdaniem nie może być poprawne skoro strzela Exception :)

0

Każdy obiekt w JAVIE ma typ przypisany do tego obiektu w postaci referencji do obiektu reprezentującego klasę - obiektu klasy Class. Bez względu na to na co przerzutujesz obiekt, obiekt zwracany przez getClass() pozostanie taki sam.

Gdyby było inaczej nie można byłoby sprawdzić typu obiektu podczas wykonania rzutowania. To na podstawie typu obiektu wyrzucany jest ewentualny ClassCastException.
Notabene tak jest właśnie w klasycznym C++, typy przypisane są raczej do wskaźników/referencji/bezpośrednich odwołań do obiektów.

0

Dziękuję wszyskim za odpowiedźi
Dalej to dla mnie nie jest do końca jasne, ale już bardziej niż było:)
widzę, że muszę wiele się uczyć

Pozdrawiam Was serdeczenie
Tomek

1 użytkowników online, w tym zalogowanych: 0, gości: 1