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

Πακέτα και στατικές εισαγωγές στην Ιάβα

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

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

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

Τύποι αναφοράς συσκευασίας

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

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

Τι είναι τα πακέτα στην Java;

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

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

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

Ένα πακέτο έχει ένα όνομα, το οποίο πρέπει να είναι μη δεσμευμένο αναγνωριστικό. για παράδειγμα, Ιάβα. Ο χειριστής πρόσβασης μέλους (.) διαχωρίζει ένα όνομα πακέτου από ένα όνομα δευτερεύουσας συσκευασίας και διαχωρίζει ένα όνομα πακέτου ή υποσυσκευασίας από ένα όνομα τύπου. Για παράδειγμα, οι δύο μέλη τελεστές πρόσβασης στο java.lang.System ξεχωριστό όνομα πακέτου Ιάβα από το lang όνομα υποσυσκευασίας και ξεχωριστό όνομα δευτερεύουσας συσκευασίας lang από το Σύστημα πληκτρολογήστε όνομα.

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

Η δήλωση πακέτου

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

 πακέτο αναγνωριστικό[.αναγνωριστικό]*; 

Μια δήλωση πακέτου ξεκινά με την δεσμευμένη λέξη πακέτο και συνεχίζεται με ένα αναγνωριστικό, το οποίο προαιρετικά ακολουθείται από μια ακολουθία αναγνωριστικών διαχωρισμένη με την περίοδο. Ένα ερωτηματικό (;) τερματίζει αυτήν τη δήλωση.

Το πρώτο αναγνωριστικό (αριστερόστροφα) ονομάζει το πακέτο και κάθε επόμενο αναγνωριστικό ονομάζει ένα δευτερεύον πακέτο. Για παράδειγμα, στο πακέτο a.b;, όλοι οι τύποι που δηλώνονται στο αρχείο προέλευσης ανήκουν στο σι υπο συσκευασία του ένα πακέτο.

Σύμβαση ονομασίας πακέτων / υποσυσκευασιών

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

Μια ακολουθία ονομάτων πακέτων πρέπει να είναι μοναδική για την αποφυγή προβλημάτων συλλογής. Για παράδειγμα, ας υποθέσουμε ότι δημιουργείτε δύο διαφορετικά γραφικά πακέτα και υποθέστε ότι το καθένα γραφικά το πακέτο περιέχει ένα Τρίγωνο τάξη με διαφορετική διεπαφή. Όταν ο μεταγλωττιστής Java συναντά κάτι σαν αυτό που ακολουθεί, πρέπει να επαληθεύσει ότι το Τρίγωνο (int, int, int, int) ο κατασκευαστής υπάρχει:

 Τρίγωνο t = νέο τρίγωνο (1, 20, 30, 40); 

Τριγωνικό κουτί οριοθέτησης

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

Ο μεταγλωττιστής θα αναζητήσει όλα τα προσβάσιμα πακέτα μέχρι να βρει ένα γραφικά πακέτο που περιέχει Τρίγωνο τάξη. Εάν το πακέτο που βρέθηκε περιλαμβάνει το κατάλληλο Τρίγωνο τάξη με ένα Τρίγωνο (int, int, int, int) κατασκευαστής, όλα είναι καλά. Διαφορετικά, εάν βρεθεί Τρίγωνο η τάξη δεν έχει Τρίγωνο (int, int, int, int) κατασκευαστή, ο μεταγλωττιστής αναφέρει ένα σφάλμα. (Θα πω περισσότερα για τον αλγόριθμο αναζήτησης αργότερα σε αυτό το σεμινάριο.)

Αυτό το σενάριο δείχνει τη σημασία της επιλογής μοναδικών ακολουθιών ονόματος πακέτου. Η σύμβαση για την επιλογή μιας μοναδικής ακολουθίας ονομάτων είναι η αντιστροφή του ονόματος τομέα διαδικτύου και η χρήση του ως πρόθεμα για την ακολουθία. Για παράδειγμα, θα επέλεγα ca. javajeff ως πρόθεμά μου γιατί javajeff.ca είναι το όνομα τομέα μου. Στη συνέχεια, θα διευκρινίσω ca.javajeff.graphics.Triangle για να έχω πρόσβαση σε Τρίγωνο.

Στοιχεία ονόματος τομέα και έγκυρα ονόματα πακέτων

Τα στοιχεία ονόματος τομέα δεν είναι πάντα έγκυρα ονόματα πακέτων. Ένα ή περισσότερα ονόματα συστατικών ενδέχεται να ξεκινούν με ένα ψηφίο (3D.com), περιέχει παύλα (-) ή άλλο παράνομο χαρακτήρα (ab-z.comή να είναι μία από τις δεσμευμένες λέξεις της Java (short.com). Η Σύμβαση υπαγορεύει ότι το πρόθεμα του ψηφίου με μια υπογράμμιση (com._3D), αντικαταστήστε τον παράνομο χαρακτήρα με μια υπογράμμιση (com.ab_z) και επίθημα της δεσμευμένης λέξης με μια υπογράμμιση (com.short_).

Πρέπει να ακολουθήσετε μερικούς κανόνες για να αποφύγετε πρόσθετα προβλήματα με τη δήλωση πακέτου:

  1. Μπορείτε να δηλώσετε μόνο μία δήλωση πακέτου σε ένα αρχείο προέλευσης.
  2. Δεν μπορείτε να προηγηθεί η δήλωση πακέτου με τίποτα εκτός από σχόλια.

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

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

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

Παράδειγμα: Συσκευασία μιας βιβλιοθήκης ήχου στην Java

Ένα πρακτικό παράδειγμα είναι χρήσιμο για την πλήρη κατανόηση του πακέτο δήλωση. Σε αυτήν την ενότητα παρουσιάζω πακέτα στο πλαίσιο μιας βιβλιοθήκης ήχου που σας επιτρέπει να διαβάζετε αρχεία ήχου και να λαμβάνετε δεδομένα ήχου. Για συντομία, θα παρουσιάσω μόνο μια σκελετική έκδοση της βιβλιοθήκης.

Η βιβλιοθήκη ήχου αποτελείται από δύο μόνο κατηγορίες: Ήχος και WavReader. Ήχος περιγράφει ένα ηχητικό κλιπ και είναι η κύρια τάξη της βιβλιοθήκης. Η λίστα 1 παρουσιάζει τον πηγαίο κώδικα.

Λίστα 1. Παράδειγμα δήλωσης πακέτου (Audio.java)

 πακέτο ca.javajeff.audio; δημόσια τελική κλάση ήχου {ιδιωτικό int [] δείγματα? ιδιωτικό int sampleRate; Ήχος (int [] δείγματα, int sampleRate) {this.samples = samples; this.sampleRate = sampleRate; } δημόσια int [] getSamples () {δείγματα επιστροφής; } public int getSampleRate () {return sampleRate; } δημόσιο στατικό ήχο newAudio (String όνομα αρχείου) {if (filename.toLowerCase (). berakhirWith (". wav")) επιστροφή WavReader.read (όνομα αρχείου); αλλιώς επιστρέψτε null? // μορφή που δεν υποστηρίζεται } } 

Ας δούμε την Λίστα 1 βήμα προς βήμα.

  • ο Audio.java αρχείο στην καταχώριση 1 αποθηκεύει το Ήχος τάξη. Αυτή η λίστα ξεκινά με μια δήλωση πακέτου που προσδιορίζει ca.javajeff.audio ως το πακέτο της τάξης.
  • Ήχος δηλώνεται δημόσιο έτσι ώστε να μπορεί να αναφέρεται έξω από το πακέτο του. Επίσης, δηλώνεται τελικός έτσι ώστε να μην μπορεί να επεκταθεί (που σημαίνει, υποκατηγοριοποιείται).
  • Ήχος δηλώνει ιδιωτικόςδείγματα και ρυθμός δειγματοληψίας πεδία για την αποθήκευση δεδομένων ήχου. Αυτά τα πεδία αρχικοποιούνται στις τιμές που μεταβιβάζονται ΉχοςΚατασκευαστής.
  • Ήχοςδηλώνεται ο κατασκευαστής πακέτο-ιδιωτικό (δηλαδή, ο κατασκευαστής δεν δηλώνεται δημόσιο, ιδιωτικός, ή προστατευμένο) έτσι ώστε αυτή η τάξη να μην μπορεί να δημιουργηθεί από έξω από το πακέτο της.
  • Ήχος παρουσιάζει getSamples () και getSampleRate () μέθοδοι για την επιστροφή των δειγμάτων ενός κλιπ ήχου και του ρυθμού δειγματοληψίας. Κάθε μέθοδος δηλώνεται δημόσιο έτσι ώστε να μπορεί να καλείται από έξω από το Ήχοςπακέτο.
  • Ήχος τελειώνει με ένα δημόσιο και στατικόςνέοAudio () εργοστασιακή μέθοδος επιστροφής ενός Ήχος αντικείμενο που αντιστοιχεί στο όνομα αρχείου διαφωνία. Εάν δεν είναι δυνατή η λήψη του κλιπ ήχου, μηδενικό επιστρέφεται.
  • νέοAudio () συγκρίνει όνομα αρχείουεπέκταση με . wav (αυτό το παράδειγμα υποστηρίζει μόνο ήχο WAV). Αν ταιριάζουν, εκτελείται επιστροφή WavReader.read (όνομα αρχείου) για να επιστρέψετε ένα Ήχος αντικείμενο με δεδομένα ήχου που βασίζονται σε WAV.

Η λίστα 2 περιγράφει WavReader.

Λίστα 2. Η τάξη βοηθού WavReader (WavReader.java)

 πακέτο ca.javajeff.audio; τελική κλάση WavReader {στατική ανάγνωση ήχου (String όνομα αρχείου) {// Διαβάστε τα περιεχόμενα του αρχείου ονόματος αρχείου και επεξεργαστείτε το // σε μια σειρά τιμών δείγματος και δείγματος ρυθμού // τιμή. Εάν δεν είναι δυνατή η ανάγνωση του αρχείου, επιστρέψτε το null. Για το // brevity (και επειδή δεν έχω συζητήσει ακόμη για το // αρχείο I / O API της Java), παρουσιάζω μόνο σκελετικό κώδικα που // επιστρέφει πάντα ένα αντικείμενο ήχου με προεπιλεγμένες τιμές. επιστροφή νέου ήχου (νέο int [0], 0); }} 

WavReader προορίζεται να διαβάσει τα περιεχόμενα ενός αρχείου WAV σε ένα Ήχος αντικείμενο. (Η τάξη θα είναι τελικά μεγαλύτερη με επιπλέον ιδιωτικός πεδία και μέθοδοι.) Παρατηρήστε ότι αυτή η τάξη δεν έχει δηλωθεί δημόσιο, που κάνει WavReader προσβάσιμο σε Ήχος αλλά όχι για κωδικοποίηση εκτός του ca.javajeff.audio πακέτο. Σκέφτομαι WavReader ως βοηθητική τάξη της οποίας ο μόνος λόγος ύπαρξης είναι η εξυπηρέτηση Ήχος.

Ολοκληρώστε τα παρακάτω βήματα για να δημιουργήσετε αυτήν τη βιβλιοθήκη:

  1. Επιλέξτε μια κατάλληλη τοποθεσία στο σύστημα αρχείων σας ως τον τρέχοντα κατάλογο.
  2. Δημιουργώ ένα ca / javajeff / ήχος ιεραρχία υποκαταλόγου στον τρέχοντα κατάλογο.
  3. Αντιγράψτε τις λίστες 1 και 2 σε αρχεία Audio.java και WavReader.java, αντίστοιχα · και αποθηκεύστε αυτά τα αρχεία στο ήχος υποκατάλογος
  4. Υποθέτοντας ότι ο τρέχων κατάλογος περιέχει το περ υποκατάλογος, εκτέλεση javac ca / ​​javajeff / audio / *. java για να μεταγλωττίσετε τα δύο αρχεία προέλευσης ca / javajeff / ήχος. Αν όλα πάνε καλά, πρέπει να το ανακαλύψετε Audio.class και WavReader.class αρχεία στο ήχος υποκατάλογος (Εναλλακτικά, για αυτό το παράδειγμα, μπορείτε να μεταβείτε στο ήχος υποκατάλογο και εκτέλεση javac * .java.)

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

Δήλωση εισαγωγής Java

Φανταστείτε να πρέπει να καθορίσετε ca.javajeff.graphics.Triangle για κάθε εμφάνιση του Τρίγωνο στον πηγαίο κώδικα, επανειλημμένα. Η Java παρέχει τη δήλωση εισαγωγής ως μια βολική εναλλακτική λύση για την παράλειψη μεγάλων λεπτομερειών πακέτου.

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

 εισαγωγή αναγνωριστικό[.αναγνωριστικό]*.(πληκτρολογήστε Όνομα | *); 

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

Η σύνταξη αποκαλύπτει δύο μορφές της δήλωσης εισαγωγής. Πρώτον, μπορείτε να εισαγάγετε ένα όνομα τύπου, το οποίο προσδιορίζεται μέσω πληκτρολογήστε Όνομα. Δεύτερον, μπορείτε να εισαγάγετε όλους τους τύπους, οι οποίοι αναγνωρίζονται μέσω του αστερίσκου.

ο * Το σύμβολο είναι ένα μπαλαντέρ που αντιπροσωπεύει όλα τα μη αναγνωρισμένα ονόματα τύπων. Λέει στον μεταγλωττιστή να ψάξει για τέτοια ονόματα στο πιο δεξιό πακέτο της ακολουθίας πακέτων της δήλωσης εισαγωγής, εκτός εάν το όνομα τύπου βρίσκεται σε πακέτο που έχει ήδη αναζητηθεί. Σημειώστε ότι η χρήση του μπαλαντέρ δεν έχει ποινή απόδοσης ή οδηγεί σε bloat κώδικα. Ωστόσο, μπορεί να οδηγήσει σε διενέξεις ονομάτων, τις οποίες θα δείτε.

Για παράδειγμα, εισαγωγή ca.javajeff.graphics.Triangle; λέει στον μεταγλωττιστή ότι ένα ακατάλληλο Τρίγωνο υπάρχει τάξη στο ca.javajeff.graphics πακέτο. Ομοίως, κάτι σαν

 εισαγωγή ca.javajeff.graphics. *; 

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

Αποφύγετε τα * σε έργα πολλαπλών προγραμματιστών

Όταν εργάζεστε σε ένα έργο πολλαπλών προγραμματιστών, αποφύγετε τη χρήση του * μπαλαντέρ, ώστε άλλοι προγραμματιστές να βλέπουν εύκολα ποιοι τύποι χρησιμοποιούνται στον πηγαίο κώδικα.