Προγραμματισμός

Αρχικοποίηση κλάσης και αντικειμένων σε Java

Τα μαθήματα και τα αντικείμενα στην Java πρέπει να προετοιμαστούν πριν από τη χρήση τους. Στο παρελθόν μάθατε ότι τα πεδία κλάσης αρχικοποιούνται σε προεπιλεγμένες τιμές όταν φορτώνονται τάξεις και ότι τα αντικείμενα αρχικοποιούνται μέσω κατασκευαστών, αλλά υπάρχουν περισσότερα για την προετοιμασία. Αυτό το άρθρο παρουσιάζει όλες τις δυνατότητες της Java για την προετοιμασία τάξεων και αντικειμένων.

λήψη Λήψη του κώδικα Λήψη του πηγαίου κώδικα για παράδειγμα εφαρμογές σε αυτό το σεμινάριο. Δημιουργήθηκε από τον Jeff Friesen για το JavaWorld.

Πώς να ξεκινήσετε μια τάξη Java

Προτού διερευνήσουμε την υποστήριξη της Java για την προετοιμασία της τάξης, ας ανακεφαλαιώσουμε τα βήματα της αρχικοποίησης μιας κλάσης Java. Εξετάστε την καταχώριση 1.

Λίστα 1. Αρχικοποίηση πεδίων κλάσης σε προεπιλεγμένες τιμές

τάξη SomeClass {static boolean b; στατικό byte από; στατικός χαρακτήρας c; στατικό διπλό d; στατικό float f; στατικό int i; στατικό μακρύ l; στατικό σύντομο s; στατικό String st; }

Η λίστα 1 δηλώνει τάξη SomeClass. Αυτή η τάξη δηλώνει εννέα πεδία τύπων boolean, ψηφιόλεξη, απανθρακώνω, διπλό, φλοτέρ, int, μακρύς, μικρός, και Σειρά. Πότε SomeClass φορτώνεται, τα bit κάθε πεδίου ορίζονται στο μηδέν, το οποίο ερμηνεύετε ως εξής:

false 0 \ u0000 0,0 0,0 0 0 0 null

Τα προηγούμενα πεδία τάξης αρχικοποιήθηκαν σιωπηρά στο μηδέν. Ωστόσο, μπορείτε επίσης να προετοιμάσετε ρητά τα πεδία τάξης εκχωρώντας απευθείας τιμές σε αυτά, όπως φαίνεται στην καταχώριση 2.

Λίστα 2. Αρχικοποίηση πεδίων τάξης σε ρητές τιμές

τάξη SomeClass {static boolean b = true; στατικό byte = 1; στατικός χαρακτήρας c = 'A'; στατικό διπλό d = 2.0; στατικό float f = 3.0f; στατικό int i = 4; στατικό μήκος l = 5000000000L; στατικό σύντομο s = 20000; στατική συμβολοσειρά st = "abc"; }

Η τιμή κάθε εργασίας πρέπει να είναι συμβατή με τον τύπο του πεδίου κλάσης. Κάθε μεταβλητή αποθηκεύει την τιμή απευθείας, με εξαίρεση το αγ. Μεταβλητός αγ αποθηκεύει μια αναφορά σε ένα Σειρά αντικείμενο που περιέχει αλφάβητο.

Αναφορά πεδίων τάξης

Κατά την προετοιμασία ενός πεδίου τάξης, είναι νόμιμο να το αρχικοποιήσετε στην τιμή ενός πεδίου κλάσης που είχε αρχικά προετοιμαστεί. Για παράδειγμα, η καταχώριση 3 αρχικοποιεί γ προς την Χαξία. Και τα δύο πεδία προετοιμάζονται σε 2.

Λίστα 3. Αναφορά ενός πεδίου που δηλώθηκε προηγουμένως

τάξη SomeClass {static int x = 2; στατικό int y = x; Δημόσιο στατικό κενό (String [] args) {System.out.println (x); System.out.println (y); }}

Ωστόσο, το αντίστροφο δεν είναι νόμιμο: δεν μπορείτε να ξεκινήσετε ένα πεδίο κλάσης στην τιμή ενός πεδίου κλάσης που δηλώθηκε στη συνέχεια. Ο μεταγλωττιστής Java εξέρχεται παράνομη προθεσμιακή αναφορά όταν συναντά αυτό το σενάριο. Εξετάστε την καταχώριση 4.

Λίστα 4. Απόπειρα αναφοράς πεδίου που δηλώθηκε στη συνέχεια

τάξη SomeClass {static int x = y; στατικό int y = 2; Δημόσιο στατικό κενό (String [] args) {System.out.println (x); System.out.println (y); }}

Ο μεταγλωττιστής θα αναφέρει παράνομη προθεσμιακή αναφορά όταν συναντά στατικό int x = y;. Αυτό συμβαίνει επειδή ο πηγαίος κώδικας καταρτίζεται από πάνω προς τα κάτω και ο μεταγλωττιστής δεν έχει δει ακόμη γ. (Θα εκδώσει επίσης αυτό το μήνυμα εάν γ δεν ξεκίνησε ρητά.)

Μπλοκ αρχικοποίησης τάξης

Σε ορισμένες περιπτώσεις μπορεί να θέλετε να εκτελέσετε σύνθετες αρχικοποιήσεις βάσει τάξης. Αυτό θα το κάνετε μετά τη φόρτωση μιας κλάσης και πριν από τη δημιουργία αντικειμένων από αυτήν την κλάση (υποθέτοντας ότι η κλάση δεν είναι κλάση χρησιμότητας). Μπορείτε να χρησιμοποιήσετε ένα μπλοκ αρχικοποίησης τάξης για αυτήν την εργασία.

ΕΝΑ μπλοκ αρχικοποίησης τάξης είναι ένα μπλοκ δηλώσεων πριν από το στατικός λέξη-κλειδί που εισάγεται στο σώμα της τάξης. Όταν φορτώνεται η τάξη, εκτελούνται αυτές οι δηλώσεις. Εξετάστε την καταχώριση 5.

Λίστα 5. Αρχικοποίηση συστοιχιών τιμών ημιτονοειδούς και συνημίτου

τάξη Γραφικά {στατικά διπλά [] ημίτονα, συνημίτονα; στατικό {sines = νέο διπλό [360]; cosines = νέο διπλό [360]; για (int i = 0; i <sines.length; i ++) {sines [i] = Math.sin (Math.toRadians (i)); cosines [i] = Math.cos (Math.toRadians (i)); }}}

Η λίστα 5 δηλώνει α Γραφικά τάξη που δηλώνει ημι και συνημίτονα μεταβλητές πίνακα. Δηλώνει επίσης ένα μπλοκ αρχικοποίησης κλάσης που δημιουργεί πίνακες 360 στοιχείων στα οποία έχουν ανατεθεί οι αναφορές ημι και συνημίτονα. Στη συνέχεια χρησιμοποιεί ένα Για δήλωση για την αρχικοποίηση αυτών των στοιχείων συστοιχίας στις κατάλληλες ημιτονοειδείς και συνημίτονες τιμές, καλώντας το Μαθηματικά της τάξης αμαρτία() και cos () μεθόδους. (Μαθηματικά είναι μέρος της τυπικής βιβλιοθήκης κατηγορίας Java. Θα συζητήσω αυτήν την τάξη και αυτές τις μεθόδους σε μελλοντικό άρθρο.)

Κόλπο απόδοσης

Επειδή η απόδοση είναι σημαντική για τις εφαρμογές γραφικών και επειδή είναι πιο γρήγορη η πρόσβαση σε ένα στοιχείο πίνακα από το να καλέσουμε μια μέθοδο, οι προγραμματιστές καταφεύγουν σε κόλπα απόδοσης όπως η δημιουργία και η προετοιμασία συστοιχιών ημιτονοειδών και συνημίτων.

Συνδυάζοντας αρχικοποιητές πεδίου κλάσης και μπλοκ αρχικοποίησης κλάσης

Μπορείτε να συνδυάσετε πολλούς αρχικοποιητές πεδίων κλάσης και μπλοκ αρχικοποίησης κλάσης σε μια εφαρμογή. Η λίστα 6 παρέχει ένα παράδειγμα.

Λίστα 6. Εκτέλεση αρχικοποίησης τάξης από πάνω προς τα κάτω

τάξη MCFICIB {static int x = 10; στατική διπλή θερμοκρασία = 98,6; στατικό {System.out.println ("x =" + x); temp = (temp - 32) * 5.0 / 9.0; // μετατροπή σε Celsius System.out.println ("temp =" + temp); } στατικό int y = x + 5; στατικό {System.out.println ("y =" + y); } δημόσιος στατικός κενός κενός (String [] args) {}}

Η λίστα 6 δηλώνει και αρχικοποιεί ένα ζευγάρι πεδίων τάξης (Χ και γ), και δηλώνει ένα ζευγάρι στατικός αρχικοποιητές. Συντάξτε αυτήν την καταχώριση όπως φαίνεται:

javac MCFICIB.java

Στη συνέχεια, εκτελέστε την εφαρμογή που προκύπτει:

java MCFICIB

Πρέπει να παρατηρήσετε την ακόλουθη έξοδο:

x = 10 temp = 37,0 y = 15

Αυτή η έξοδος αποκαλύπτει ότι η αρχικοποίηση κλάσης πραγματοποιείται με σειρά από πάνω προς τα κάτω.

() μέθοδοι

Κατά την κατάρτιση αρχικοποιητών κλάσης και μπλοκ αρχικοποίησης κλάσης, ο μεταγλωττιστής Java αποθηκεύει τον μεταγλωττισμένο bytecode (με σειρά από πάνω προς τα κάτω) σε μια ειδική μέθοδο που ονομάζεται (). Τα γωνιακά στηρίγματα αποτρέπουν ένα σύγκρουση ονόματος: δεν μπορείτε να δηλώσετε a () μέθοδος στον πηγαίο κώδικα επειδή το < και > οι χαρακτήρες είναι παράνομοι σε ένα περιβάλλον αναγνώρισης.

Μετά τη φόρτωση μιας κλάσης, η JVM καλεί αυτήν τη μέθοδο πριν την κλήση κύριος() (πότε κύριος() είναι παρών).

Ας ρίξουμε μια ματιά μέσα MCFICIB.class. Η ακόλουθη μερική αποσυναρμολόγηση αποκαλύπτει τις αποθηκευμένες πληροφορίες για το Χ, θερμοκρασία, και γ πεδία:

Πεδίο # 1 00000290 Σημαίες πρόσβασης ACC_STATIC 00000292 Όνομα x 00000294 Περιγραφέας I 00000296 Αριθμός χαρακτηριστικών 0 Πεδίο # 2 00000298 Σημαίες πρόσβασης ACC_STATIC 0000029a Όνομα temp 0000029c Περιγραφέας D 0000029e Καταμέτρηση χαρακτηριστικών 0 Πεδίο # 3 000002a0 Σημαίες πρόσβασης ACC_STATIC 000002a200000000000000000000002 0

ο Περιγραφέας γραμμή προσδιορίζει τα JVM's περιγραφέας τύπου για το γήπεδο. Ο τύπος αντιπροσωπεύεται με ένα μόνο γράμμα: Εγώ Για int και ρε Για διπλό.

Η ακόλουθη μερική αποσυναρμολόγηση αποκαλύπτει την ακολουθία εντολών bytecode για το () μέθοδος. Κάθε γραμμή ξεκινά με έναν δεκαδικό αριθμό που προσδιορίζει τη διεύθυνση μετατόπισης με βάση το μηδέν της επόμενης εντολής:

 0 bipush 10 2 putstatic MCFICIB / x I 5 ldc2_w # 98.6 8 putstatic MCFICIB / temp D 11 getstatic java / lang / System / out Ljava / io / PrintStream; 14 νέα java / lang / StringBuilder 17 dup 18 invokespecial java / lang / StringBuilder / () V 21 ldc "x =" 23 invokevirtual java / lang / StringBuilder / append (Ljava / lang / String;) Ljava / lang / StringBuilder; 26 getstatic MCFICIB / x I 29 invokevirtual java / lang / StringBuilder / append (I) Ljava / lang / StringBuilder; 32 invokevirtual java / lang / StringBuilder / toString () Ljava / lang / String; 35 invokevirtual java / io / PrintStream / println (Ljava / lang / String;) V 38 getstatic MCFICIB / temp D 41 ldc2_w # 32 44 dsub 45 ldc2_w # 5 48 dmul 49 ldc2_w # 9 52 ddiv 53 putstatic MCFICIB / temp D 56 getstatic java / lang / System / out Ljava / io / PrintStream; 59 νέα java / lang / StringBuilder 62 dup 63 invokespecial java / lang / StringBuilder / () V 66 ldc "temp =" 68 invokevirtual java / lang / StringBuilder / append (Ljava / lang / String;) Ljava / lang / StringBuilder; 71 getstatic MCFICIB / temp D 74 invokevirtual java / lang / StringBuilder / append (D) Ljava / lang / StringBuilder; 77 invokevirtual java / lang / StringBuilder / toString () Ljava / lang / String; 80 invokevirtual java / io / PrintStream / println (Ljava / lang / String;) V 83 getstatic MCFICIB / x I 86 iconst_5 87 iadd 88 putstatic MCFICIB / y I 91 getstatic java / lang / System / out Ljava / io / PrintStream; 94 new java / lang / StringBuilder 97 dup 98 invokespecial java / lang / StringBuilder / () V 101 ldc "y =" 103 invokevirtual java / lang / StringBuilder / append (Ljava / lang / String;) Ljava / lang / StringBuilder; 106 getstatic MCFICIB / y I 109 invokevirtual java / lang / StringBuilder / append (I) Ljava / lang / StringBuilder; 112 invokevirtual java / lang / StringBuilder / toString () Ljava / lang / String; 115 invokevirtual java / io / PrintStream / println (Ljava / lang / String;) V 118 επιστροφή

Η ακολουθία εντολών από το όφσετ 0 έως το όφσετ 2 είναι ισοδύναμη με τον ακόλουθο αρχικοποιητή πεδίου κλάσης:

στατικό int x = 10;

Η ακολουθία εντολών από την όφσετ 5 έως την όφσετ 8 είναι ισοδύναμη με τον ακόλουθο αρχικοποιητή πεδίου κλάσης:

στατική διπλή θερμοκρασία = 98,6;

Η ακολουθία εντολών από το όφσετ 11 έως το όφσετ 80 είναι ισοδύναμη με το ακόλουθο μπλοκ αρχικοποίησης κλάσης:

στατικό {System.out.println ("x =" + x); temp = (temp - 32) * 5.0 / 9.0; // μετατροπή σε Celsius System.out.println ("temp =" + temp); }

Η ακολουθία εντολών από την όφσετ 83 έως την όφσετ 88 είναι ισοδύναμη με τον ακόλουθο αρχικοποιητή πεδίου κλάσης:

στατικό int y = x + 5;

Η ακολουθία εντολών από το όφσετ 91 έως το όφσετ 115 είναι ισοδύναμη με το ακόλουθο μπλοκ αρχικοποίησης κλάσης:

στατικό {System.out.println ("y =" + y); }

Τέλος, το ΕΠΙΣΤΡΟΦΗ Η εντολή στο offset 118 επιστρέφει την εκτέλεση από () σε αυτό το μέρος του JVM που κάλεσε αυτή τη μέθοδο.

Μην ανησυχείτε για το τι σημαίνει ο κωδικός bytecode

Η απομάκρυνση από αυτήν την άσκηση είναι να δούμε ότι όλος ο κώδικας στην αρχική θέση πεδίου της κατηγορίας της λίστας 6 και στα μπλοκ αρχικοποίησης κλάσης βρίσκεται στο () μέθοδος, και εκτελείται με σειρά από πάνω προς τα κάτω.

Πώς να αρχικοποιήσετε αντικείμενα

Αφού φορτωθεί και αρχικοποιηθεί ένα μάθημα, συχνά θέλετε να δημιουργήσετε αντικείμενα από την τάξη. Όπως μάθατε στην πρόσφατη εισαγωγή μου στον προγραμματισμό με τάξεις και αντικείμενα, αρχικοποιείτε ένα αντικείμενο μέσω του κώδικα που τοποθετείτε στον κατασκευαστή μιας τάξης. Εξετάστε την καταχώριση 7.

Λίστα 7. Χρήση του κατασκευαστή για την προετοιμασία ενός αντικειμένου

class City {ιδιωτικό όνομα συμβολοσειράς; int πληθυσμός; Πόλη (Όνομα συμβολοσειράς, int πληθυσμός) {this.name = name; this.population = πληθυσμός; } @Override public String toString () {return name + ":" + πληθυσμός; } public static void main (String [] args) {City newYork = new City ("Νέα Υόρκη", 8491079); System.out.println (newYork); // Έξοδος: Νέα Υόρκη: 8491079}}

Η λίστα 7 δηλώνει α Πόλη τάξη με όνομα και πληθυσμός πεδία. Όταν ένα Πόλη δημιουργείται αντικείμενο, το Πόλη (Όνομα συμβολοσειράς, int πληθυσμός) Ο κατασκευαστής καλείται να προετοιμάσει αυτά τα πεδία στα ορίσματα των καλούμενων κατασκευαστών. (Έχω επίσης παρακάμψει Αντικείμενο'μικρό δημόσια συμβολοσειρά toString () μέθοδος για να επιστρέψετε εύκολα το όνομα της πόλης και την τιμή του πληθυσμού ως συμβολοσειρά. System.out.println () καλεί τελικά αυτή τη μέθοδο για να επιστρέψει την παράσταση συμβολοσειράς του αντικειμένου, την οποία εξάγει.)

Πριν καλείται ο κατασκευαστής, τι κάνουν οι τιμές όνομα και πληθυσμός περιέχω? Μπορείτε να μάθετε εισάγοντας System.out.println (this.name); System.out.println (this.population); στην αρχή του κατασκευαστή. Μετά τη σύνταξη του πηγαίου κώδικα (javac City.java) και εκτέλεση της εφαρμογής (πόλη της Ιάβα), θα παρατηρούσατε μηδενικό Για όνομα και 0 Για πληθυσμός. ο νέος ο τελεστής μηδενίζει τα πεδία αντικειμένου ενός αντικειμένου (παράδειγμα) πριν εκτελέσει έναν κατασκευαστή.

Όπως και με τα πεδία τάξης, μπορείτε να προετοιμάσετε ρητά τα πεδία αντικειμένων. Για παράδειγμα, μπορείτε να καθορίσετε Όνομα συμβολοσειράς = "New York"; ή int πληθυσμός = 8491079;. Ωστόσο, συνήθως δεν υπάρχει τίποτα να κερδίσουμε κάνοντας αυτό, επειδή αυτά τα πεδία θα αρχικοποιηθούν στον κατασκευαστή. Το μόνο όφελος που μπορώ να σκεφτώ είναι να εκχωρήσω μια προεπιλεγμένη τιμή σε ένα πεδίο αντικειμένου. αυτή η τιμή χρησιμοποιείται όταν καλείτε έναν κατασκευαστή που δεν προετοιμάζει το πεδίο:

int numDoors = 4; // η προεπιλεγμένη τιμή εκχωρήθηκε στο numDoors Car (String make, String model, int year) {this (make, model, year, numDoors); } Αυτοκίνητο (String make, String model, int year, int numDoors) {this.make = make; this.model = μοντέλο; αυτό. έτος = έτος; this.numDoors = numDoors; }

Η αρχικοποίηση αντικειμένων αντικατοπτρίζει την αρχικοποίηση κλάσης