Page 1 of 1

Casting στην Java

Posted: Tue Jul 08, 2008 10:13 am
by sandra
Καλημέρα. Έχω κάμποσες απορίες με τα αντικείμενα αν μπορεί κάποιος να με βοηθήσει να τα ξεκαθαρίσω.

Έστω ότι έχω δυο τάξεις την Ρ1 και την υποκλάσση της Ρ2. Η Ρ1 έχει μόνο μια μεταβλητή k ενώ η στην Ρ2 έχω ορίσει μόνο την l.
Εάν κάνω:

Code: Select all

P1 one = new P2(); 
το one τι τύπου είναι? Η getClass μου το δίνει μόνο Ρ2 ενώ η instanceof και Ρ1 και Ρ2. Καταλαβαίνω ότι αν είναι Ρ2 είναι λογικό να συμβαίνει αυτό αλλά δεν πιάνω γιατί δεν μπορώ να δω με το one την μεταβλητή l αλλά βλέπω μόνο την k :???: Για να δω και την l πρέπει να κάνω

Code: Select all

((P2)one).l
Εάν τώρα κάνω

Code: Select all

Ρ2 two = (P1)new P2();
στο compile όλα καλά αλλά κατά την εκτέλεση μου σκάει
Exception in thread "main" java.lang.ClassCastException: P1 cannot be cast to P2
Η λογική λέει ότι ένα αντικείμενο Ρ1 δεν είναι απαραίτητα Ρ2 γιαυτό και το πρόβλημα. Αλλά συνεχίζω να μην καταλαβαίνω σε μια τέτοια δήλωση τι τύπου θα είναι το αντικείμενο.

Αν μπορεί να μου εξηγήσει κάποιος τι συμβαίνει στα παρασκήνια :oops: :)

Re: Casting στην Java

Posted: Tue Jul 08, 2008 10:51 am
by Fairy
Θα κάνω μια προσπάθεια, κι αν έχω επηρρεαστεί βλακωδώς από την C++ ας με διωρθώσει κάποιος (όχι για μένα, αλλά να σώσει και την κοπέλα!)

Όταν γράφεις κώδικα της μορφής

Code: Select all

P1 one = new P2(); 
δημιουργείς μια αναφορά τύπου P1 η οποία δείχνει σε ένα αντικείμενο P2.

Αυτό επιτρέπεται γιατί η τάξη P1 είναι υπερκλάση (και γενικότερη αν θες) της ειδικότερης P2.
Η P2 ως υποτάξη διαθέτει χαρακτηριστικά τόσο δικά της (l) όσο και της P1 (k).
Με μια αναφορά τύπου P1 που φτιάχνεις παραπάνω, λογικά μπορείς να δεις μόνο εκείνα τα χαρακτηριστικά που κληρονομούνται από την υπερτάξη και είναι γνωστά στην P1. Για να δεις και το k και το l πρέπει να φτιάξεις μια αναφορά τύπου P2, ως εξής:

Code: Select all

P2 two = new P2(); 
Από την άλλη δε νομίζω να έχει νόημα και πολύ ο κώδικας

Code: Select all

Ρ2 two = (P1)new P2();
από τη στιγμή που έτσι κι αλλιώς το αντικείμενο P2 διαθέτει τα χαρακτηριστικά της υπερτάξης P1.

O γενικός κανόνας πάντως (αν δεν μπερδεύομαι από τη C++) λέει:
Πως μια δήλωση της μορφής

ΧΤάξη <όνομα αντικ> = new ΨΤάξη();

δημιουργεί μια αναφορά (δείκτη στη μνήμη δηλαδή) προς ένα αντικείμενο τύπου ΨΤάξη. Η αναφορά αυτή είναι εργαλείο που δουλεύει σύμφωνα με τους κανόνες της ΧΤάξης.

Re: Casting στην Java

Posted: Tue Jul 08, 2008 1:12 pm
by tsilochr
η getClass() είναι μια μέθοδος που σου δίνει την κλάσση του αντικεμένου σου σε runtime, το instanceof είναι ένας τελεστής (όπως το < ή το >=) και αποφασίζει true αν το όρισμα στα αριστερά του τελεστή ανήκει στο δέντρο κληρονομικότητας της κλάσης στα δεξιά του τελεστή

Όταν κάνεις

Code: Select all

P1 one = new P2()
στη μνήμη φτιάχνεται ένα Ρ2 (με k και l) αλλά μέσω της αναφοράς one μπορείς να το χειριστείς μόνο ως Ρ1, δηλαδή να δεις μόνο το k. Αν πεις one.getClass() θα σου επιστρέψει Ρ2 γιατί στη μνήμη είναι όντως P2. Επίσης, τα αντικείμενα τύπου Ρ2 είναι επίσης και Ρ1 άρα η instanceof δίνει true και για Ρ1 και για Ρ2.

Η εντολή

Code: Select all

((P2)one).l
λέει "πάρε το αντικείμενο που χειρίζεται η αναφορά one, κάντο cast σε (δλδ χειρήσου το ως) P2 και δες το πεδίο l." Αν το one στη μνήμη δεν ήταν Ρ2 θα πάρεις ClassCastException.

Η ClassCastException είναι απόγονος της RuntimeException και γενικά τέτοιες εξαιρέσεις ο compiler δεν σε αναγκάζει να τις πιάσεις σε try/catch (αυτό είναι άλλο θέμα)

Re: Serialization Java

Posted: Tue Jul 08, 2008 8:15 pm
by sandra
Ευχαριστώ και τους δυο σας.
Άλλη απορία άσχετη από casting σχετική με serialization. Διαβάζω ότι όταν περνάς με αυτόν τον τρόπο αντικείμενα σε ένα αρχείο δεν περνιούνται οι transient μεταβλητές και τα στατικά μέλη. Οι πρώτες ΟΚ αυτό θέλουμε να κάνουμε αλλά για το δεύτερο γιατί συμβαίνει αυτό? Δεν θα έπρεπε να περνιούνται? Έστω ένα μόνο αντίγραφο που θα κοίταζε κάθε αντικείμενο τέτοιου τύπου? :smt017
Επίσης αν ένα αρχείο υπάρχει ήδη του κάνει append τα νέα αντικείμενα ή τα γράφει πάνω στα παλιά? Με τα κινέζικά που βγάζει δύσκολο να καταλάβω.

Re: Casting στην Java

Posted: Wed Jul 09, 2008 1:07 pm
by rose
Ενα ενδιαφέρον άρθρο "γιατι χρησιμοποιούμε το transient" θα το βρείς εδώ http://www.precisejava.com/javaperf/j2s ... zation.htm
οπως είπες το θέλουμε για optimization και performance.

Sometimes, you want to have variables that are common to all objects. This is accomplished with the static modifier. Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.
http://java.sun.com/docs/books/tutorial ... svars.html

Βασικά αυτό ειναι το θέμα αφού το serialization κάνει apply μονο στο object.

Re: Casting στην Java

Posted: Wed Jul 09, 2008 1:10 pm
by sandra
Απλά θεώρησα ότι δεν είναι άχρηστες οι static μεταβλητές για το αντικείμενο. Πάντως κάτι που μου έκανε εντύπωση είναι ότι οι transient παρόλο που δεν περνιούνται στο αρχείο όταν κάνεις de-serialization αυτές περνιούνται στο αντικείμενο αλλά με μηδενικά values :)

Re: Casting στην Java

Posted: Wed Jul 09, 2008 2:03 pm
by rose
Απλά θεώρησα ότι δεν είναι άχρηστες οι static μεταβλητές για το αντικείμενο
΄

Θα έπρεπε....γενικά τα αντικείμενα θα πρέπει να είναι static independent :-D ειμαι ερωτευμένος με αυτη την λέξη! :smt024