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

Java 101: Τα πακέτα οργανώνουν τάξεις και διεπαφές

Γιατί να ανακαλύψουμε ξανά τον τροχό; Αυτό το cliche ισχύει για την ανάπτυξη λογισμικού όπου ορισμένοι προγραμματιστές ξαναγράφουν τον ίδιο κώδικα για διαφορετικά προγράμματα. Δύο μειονεκτήματα με αυτήν την προσέγγιση είναι:

  1. Χάνεται χρόνο
  2. Εισάγει τη δυνατότητα για σφάλματα στον κώδικα εντοπισμού σφαλμάτων

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

Οι βιβλιοθήκες είναι θεμελιώδεις για την Java. Επιτρέπουν, εν μέρει, στον classloader του JVM να εντοπίζει classfiles. (Θα εξερευνήσω τους φορτωτές τάξεων σε ένα μελλοντικό άρθρο.) Για το λόγο αυτό, οι βιβλιοθήκες της Java είναι συνήθως γνωστές ως βιβλιοθήκες τάξης. Ωστόσο, η Java αναφέρεται σε βιβλιοθήκες τάξεων ως πακέτα.

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

Σημείωση
Το πείραμα ενός πακέτου αυτού του άρθρου αφορά συγκεκριμένα τα Microsoft Windows. Θα πρέπει να είστε σε θέση να επεκτείνετε εύκολα αυτό το πείραμα σε πλατφόρμες εκτός Windows.

Τι είναι τα πακέτα;

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

Από την άποψη της εφαρμογής, η εξίσωση ενός πακέτου με έναν κατάλογο αποδεικνύεται χρήσιμη, όπως και η εξίσωση των τάξεων και των διεπαφών ενός πακέτου με τα αρχεία καταλόγου ενός καταλόγου. Λάβετε υπόψη άλλες προσεγγίσεις - όπως η χρήση βάσεων δεδομένων - για την εφαρμογή πακέτων, οπότε μην συνηθίζετε να εξομοιώνετε πάντα πακέτα με καταλόγους. Αλλά επειδή πολλά JVM χρησιμοποιούν καταλόγους για την εφαρμογή πακέτων, αυτό το άρθρο εξομοιώνει πακέτα με καταλόγους. Το Java 2 SDK οργανώνει την τεράστια συλλογή των τάξεων και των διεπαφών σε μια ιεραρχία πακέτων που μοιάζει με δέντρα σε πακέτα, η οποία είναι ισοδύναμη με τους καταλόγους των καταλόγων. Αυτή η ιεραρχία επιτρέπει στα Sun Microsystems να διανέμουν εύκολα (και να εργάζεστε εύκολα) αυτές τις κλάσεις και διεπαφές. Παραδείγματα πακέτων Java περιλαμβάνουν:

  • java.lang: Μια συλλογή μαθημάτων που σχετίζονται με τη γλώσσα, όπως Αντικείμενο και Σειρά, οργανωμένο στο Ιάβα πακέτο lang συσκευασία
  • java.lang.ref: Μια συλλογή από τάξεις γλωσσών που σχετίζονται με την αναφορά, όπως SoftReference και ReferenceQueue, οργανωμένο στο αναφ υπο-συσκευασία του Ιάβα πακέτο lang συσκευασία
  • javax.swing: Μια συλλογή από κλάσεις συστατικών που σχετίζονται με το Swing, όπως JButton, και διεπαφές, όπως ButtonModel, οργανωμένο στο javax πακέτο κούνια συσκευασία

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

Υπόδειξη
Ακριβώς όπως δεν μπορείτε να αποθηκεύσετε ένα αρχείο και έναν κατάλογο με ίδια ονόματα στον ίδιο κατάλογο, δεν μπορείτε να αποθηκεύσετε μια τάξη ή μια διεπαφή και ένα πακέτο με πανομοιότυπα ονόματα στο ίδιο πακέτο. Για παράδειγμα, με το όνομα ενός πακέτου λογαριασμοί, δεν μπορείτε να αποθηκεύσετε τόσο ένα πακέτο όσο και μια κλάση με το όνομα πληρωτέος σε λογαριασμοί. Για να αποφύγετε αντικρουόμενα ονόματα, κεφαλαία το πρώτο γράμμα των ονομάτων τάξης και διεπαφής και πεζά το πρώτο γράμμα των ονομάτων πακέτων. Χρησιμοποιώντας το προηγούμενο παράδειγμα, κλάση καταστήματος Πληρωτέος σε συσκευασία λογαριασμοί όπως και πληρωτέοι λογαριασμοί και πακέτο πληρωτέος σε συσκευασία λογαριασμοί όπως και πληρωτέοι λογαριασμοί. Μάθετε περισσότερα σχετικά με αυτό και άλλες συμβάσεις ονομάτων από την Sun's Συμβάσεις κώδικα για τη γλώσσα προγραμματισμού Java.

Δημιουργήστε ένα πακέτο τάξεων και διεπαφών

Οι τάξεις και οι διεπαφές κάθε αρχείου προέλευσης οργανώνονται σε ένα πακέτο. Στο πακέτο απουσία οδηγίας, αυτές οι κλάσεις και οι διασυνδέσεις ανήκουν στο πακέτο χωρίς όνομα (ο κατάλογος που ο JVM θεωρεί ως ο τρέχων κατάλογος - ο κατάλογος όπου ένα πρόγραμμα Java ξεκινά την εκτέλεση μέσω των Windows java.exe, ή ισοδύναμο με το λειτουργικό πρόγραμμα - και δεν περιέχει δευτερεύοντα πακέτα). Αλλά αν το πακέτο Η οδηγία εμφανίζεται σε ένα αρχείο προέλευσης, η οποία ορίζει το πακέτο για αυτές τις κλάσεις και διεπαφές. Χρησιμοποιήστε την ακόλουθη σύνταξη για να καθορίσετε ένα πακέτο οδηγία στον πηγαίο κώδικα:

'πακέτο' όνομα πακέτου [ '.' subpackageName ... ] ';' 

ΕΝΑ πακέτο Η οδηγία ξεκινά με το πακέτο λέξη-κλειδί. Ένα αναγνωριστικό που ονομάζει ένα πακέτο, όνομα πακέτου, αμέσως ακολουθεί. Εάν οι τάξεις και οι διασυνδέσεις θα εμφανίζονται σε ένα πακέτο (σε κάποιο επίπεδο) μέσα όνομα πακέτου, ένα ή περισσότερα διαχωρισμένα με τελεία subpackageName Τα αναγνωριστικά εμφανίζονται μετά όνομα πακέτου. Το ακόλουθο τμήμα κώδικα παρουσιάζει ένα ζευγάρι πακέτο οδηγίες:

πακέτο παιχνιδιών? πακέτο game.devices? 

Ο πρώτος πακέτο Η οδηγία προσδιορίζει ένα πακέτο που ονομάζεται παιχνίδι. Όλες οι τάξεις και οι διεπαφές που εμφανίζονται στο αρχείο προέλευσης αυτής της οδηγίας οργανώνονται στο παιχνίδι πακέτο. Το δεύτερο πακέτο Η οδηγία προσδιορίζει ένα υπο-πακέτο που ονομάζεται συσκευές, το οποίο βρίσκεται σε ένα πακέτο με το όνομα παιχνίδι. Όλες οι τάξεις και οι διεπαφές που εμφανίζονται στο αρχείο προέλευσης αυτής της οδηγίας οργανώνονται στο παιχνίδι πακέτο συσκευές συσκευασία. Εάν μια εφαρμογή JVM αντιστοιχίζει ονόματα πακέτων σε ονόματα καταλόγων, game.devices χάρτες σε ένα παιχνίδι \ συσκευές ιεραρχία καταλόγου στα Windows και a παιχνίδι / συσκευές ιεραρχία καταλόγου σε Linux ή Solaris.

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

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

Λίστα 1. A.java

// A.java πακέτο testpkg; δημόσια τάξη Α {int x = 1; δημόσιο int y = 2; προστατευμένο int z = 3; int returnx () {επιστροφή x; } δημόσια int returny () {return y; } προστατευμένο int returnz () {return z; } δημόσια διεπαφή StartStop {void start (); άκυρη στάση (); }} κλάση B {δημόσιο στατικό κενό γειά σου () {System.out.println ("γεια"); }} 

Η καταχώριση 1 εισάγει τον πηγαίο κώδικα στο πρώτο σας πακέτο. ο πακέτο testpkg; οδηγία ονομάζει αυτό το πακέτο testpkg. Στα πλαίσια testpkg είναι τάξεις ΕΝΑ και σι. Στα πλαίσια ΕΝΑ είναι τρεις δηλώσεις πεδίου, τρεις δηλώσεις μεθόδου και μια δήλωση εσωτερικής διεπαφής. Στα πλαίσια σι είναι μια δήλωση μιας μεθόδου. Ολόκληρος ο πηγαίος κώδικας αποθηκεύεται στο A.java επειδή ΕΝΑ είναι δημόσια τάξη. Η αποστολή μας: Μετατρέψτε αυτόν τον πηγαίο κώδικα σε ένα πακέτο που αποτελείται από δύο κατηγορίες και μια εσωτερική διεπαφή (ή έναν κατάλογο που περιέχει τρία αρχεία κατηγορίας). Τα παρακάτω βήματα για τα Windows εκτελούν αυτήν την εργασία:

  1. Ανοίξτε ένα παράθυρο εντολών των Windows και βεβαιωθείτε ότι βρίσκεστε στο ντο: ριζικός κατάλογος της μονάδας δίσκου (ο κύριος κατάλογος - αντιπροσωπεύεται από μια αρχική ανάστροφη κάθετο (\) χαρακτήρα). Για να το κάνετε αυτό, πληκτρολογήστε το ντο: εντολή ακολουθούμενη από το cd \ εντολή. (Εάν χρησιμοποιείτε διαφορετική μονάδα δίσκου, αντικαταστήστε την ντο: με την επιλεγμένη μονάδα δίσκου σας. Επίσης, μην ξεχάσετε να πατήσετε το πλήκτρο Enter μετά την πληκτρολόγηση μιας εντολής.)
  2. Δημιουργώ ένα testpkg κατάλογο πληκτρολογώντας md testpkg. Σημείωση: Όταν ακολουθείτε τα βήματα αυτού του άρθρου, μην πληκτρολογείτε τελείες μετά τις εντολές.
  3. Φτιαχνω, κανω testpkg τον τρέχοντα κατάλογο πληκτρολογώντας cd testpkg.
  4. Χρησιμοποιήστε ένα πρόγραμμα επεξεργασίας για να εισαγάγετε τον πηγαίο κώδικα της Καταχώρισης 1 και να αποθηκεύσετε αυτόν τον κώδικα σε ένα A.java αρχείο στο testpkg.
  5. Συντάσσω A.java πληκτρολογώντας javac A.java. Θα πρέπει να δείτε classfiles Ένα $ StartStop.class, Μια τάξη, και B. κλάση εμφανίζονται στο testpkg Ευρετήριο.

Το σχήμα 1 απεικονίζει τα βήματα 3 έως 5.

Συγχαρητήρια! Μόλις δημιουργήσατε το πρώτο σας πακέτο. Σκεφτείτε αυτό το πακέτο ότι περιέχει δύο τάξεις (ΕΝΑ και σι) και ΕΝΑενιαία εσωτερική διεπαφή (Ξεκίνα σταμάτα). Μπορείτε επίσης να σκεφτείτε αυτό το πακέτο ως κατάλογο που περιέχει τρία αρχεία κατηγορίας: Ένα $ StartStop.class, Μια τάξη, και B. κλάση.

Σημείωση
Για να ελαχιστοποιήσει τις διενέξεις ονομάτων πακέτων (ειδικά μεταξύ εμπορικών πακέτων), η Sun έχει καθιερώσει μια σύμβαση στην οποία το όνομα τομέα διαδικτύου μιας εταιρείας αντιστρέφει και προθέτει ένα όνομα πακέτου. Για παράδειγμα, μια εταιρεία με x.com ως το όνομα τομέα του Διαδικτύου και α.β ως όνομα πακέτου (ένα) ακολουθούμενο από ένα όνομα συσκευασίας (σιπροθέματα com.x προς την α.β, έχοντας ως αποτέλεσμα com.x.a.b. Το άρθρο μου δεν ακολουθεί αυτήν τη σύμβαση επειδή το testpkg Το πακέτο είναι ένα ρίξιμο σχεδιασμένο μόνο για εκπαιδευτικούς σκοπούς.

Εισαγάγετε τάξεις και διεπαφές πακέτου

Μόλις έχετε ένα πακέτο, θα θελήσετε να εισαγάγετε τάξεις ή / και διασυνδέσεις - στην πραγματικότητα, ονόματα τάξεων ή / και διεπαφών - από αυτό το πακέτο στο πρόγραμμά σας, ώστε να μπορεί να χρησιμοποιεί αυτές τις κλάσεις ή / και διεπαφές. Ένας τρόπος για να επιτευχθεί αυτή η εργασία είναι να παρέχετε το πλήρως εξειδικευμένο όνομα πακέτου (το όνομα του πακέτου και όλα τα ονόματα των πακέτων) σε κάθε μέρος όπου εμφανίζεται το όνομα τύπου αναφοράς (το όνομα της κλάσης ή της διεπαφής), όπως δείχνει η Λίστα 2:

Λίστα 2. Usetestpkg1.java

// Κατηγορία Usetestpkg1.java Το Usetestpkg1 υλοποιεί testpkg.A.StartStop {public static void main (String [] args) {testpkg.A a = new testpkg.A (); System.out.println (a.y); System.out.println (a.returny ()); Usetestpkg1 utp = νέο Usetestpkg1 (); utp.start (); utp.stop (); } δημόσια άκυρη εκκίνηση () {System.out.println ("Έναρξη"); } δημόσια άκυρη στάση () {System.out.println ("Stop"); }} 

Με πρόθεμα testpkg. προς την ΕΝΑ, Usetestpkg1 προσβάσεις testpkgτάξη ΕΝΑ σε δύο μέρη και ΕΝΑΗ εσωτερική διεπαφή Ξεκίνα σταμάτα σε ένα μέρος. Ολοκληρώστε τα παρακάτω βήματα για μεταγλώττιση και εκτέλεση Usetestpkg1:

  1. Ανοίξτε ένα παράθυρο εντολών των Windows και βεβαιωθείτε ότι βρίσκεστε στο ντο: ριζικός κατάλογος του δίσκου.
  2. Βεβαιωθείτε ότι το τάξη η μεταβλητή περιβάλλοντος δεν υπάρχει εκτελώντας ορίστε classpath =. (Συζητώ τάξη αργότερα σε αυτό το άρθρο.)
  3. Χρησιμοποιήστε ένα πρόγραμμα επεξεργασίας για να εισαγάγετε τον πηγαίο κώδικα της καταχώρισης 2 και να αποθηκεύσετε αυτόν τον κώδικα σε ένα Usetestpkg1.java αρχείο στον ριζικό κατάλογο.
  4. Συντάσσω Usetestpkg1.java πληκτρολογώντας javac Usetestpkg1.java. Θα πρέπει να δείτε το classfile Usetestpkg1.class εμφανίζονται στον ριζικό κατάλογο.
  5. Τύπος java Usetestpkg1 για να εκτελέσετε αυτό το πρόγραμμα.

Το σχήμα 2 απεικονίζει τα βήματα 3 έως 5 και δείχνει την έξοδο του προγράμματος.

Σύμφωνα με Usetestpkg1Η έξοδος, η κύριος() πρόσβαση στο νήμα της μεθόδου testpkg.A'μικρό γ πεδίο και καλεί το επιστροφή () μέθοδος. Επιπλέον, η έξοδος δείχνει μια επιτυχημένη εφαρμογή του testpkg.A.StartStop εσωτερική διεπαφή.

Για Usetestpkg1, πρόθεμα testpkg. προς την ΕΝΑ σε τρία μέρη δεν φαίνεται μεγάλη υπόθεση. Αλλά ποιος θέλει να καθορίσει ένα πλήρως καταρτισμένο πρόθεμα ονόματος πακέτου σε εκατό μέρη; Ευτυχώς, η Java προμηθεύει το εισαγωγή οδηγία για την εισαγωγή δημόσιων ονομάτων τύπου αναφοράς ενός πακέτου, οπότε δεν χρειάζεται να εισαγάγετε πλήρως προσόντα προθέματα ονόματος πακέτου. Εκφράστε ένα εισαγωγή οδηγία στον πηγαίο κώδικα μέσω της ακόλουθης σύνταξης:

'εισαγωγή' όνομα πακέτου [ '.' subpackageName ... ] '.' ( Όνομα αναφοράς | '*' ) ';' 

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

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

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

εισαγωγή java.util.Date; 

Ο προηγούμενος μονός τύπος εισαγωγή οδηγία εισάγει όνομα κλάσης Ημερομηνία στον πηγαίο κώδικα. Ως αποτέλεσμα, καθορίζετε Ημερομηνία αντί java.util. Ημερομηνία σε κάθε μέρος που το όνομα κλάσης εμφανίζεται στον πηγαίο κώδικα. Για παράδειγμα, κατά τη δημιουργία ενός Ημερομηνία αντικείμενο, καθορίστε Ημερομηνία d = νέα Ημερομηνία (); αντί java.util.Date d = νέο java.util.Date ();.

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

εισαγωγή java.util.Date; Ημερομηνία τάξης {} 

Ο μεταγλωττιστής θεωρεί το τμήμα κώδικα ως μια προσπάθεια εισαγωγής δύο τύπων αναφοράς με τον ίδιο Ημερομηνία όνομα: