Java 101: Pakej mengatur kelas dan antara muka

Mengapa mencipta semula roda? Klise itu berlaku untuk pengembangan perisian di mana sebilangan pemaju menulis semula kod yang sama untuk program yang berbeza. Dua kelemahan dengan pendekatan tersebut adalah:

  1. Ia membuang masa
  2. Ini memperkenalkan potensi bug dalam kod debug

Sebagai alternatif untuk menulis semula kod yang sama, banyak persekitaran pengembangan perisian menyediakan alat perpustakaan yang mengatur kod yang sering digunakan. Setelah pembangun menyelesaikan debug beberapa kod yang dapat digunakan kembali, mereka menggunakan alat untuk menyimpan kod tersebut di perpustakaan — satu atau lebih fail yang mengandungi kod yang sering digunakan untuk digunakan dalam pelbagai program. Semasa pembuatan program, alat penyusun atau perpustakaan mengakses perpustakaan untuk menyambungkan kod yang dirujuk ke perpustakaan program dengan program.

Perpustakaan adalah asas bagi Java. Mereka membenarkan, sebahagiannya, pemuat kelas JVM untuk mencari classfile. (Saya akan meneroka pemuat kelas dalam artikel yang akan datang.) Untuk itu, perpustakaan Java biasanya dikenali sebagai perpustakaan kelas. Namun, Java merujuk kepada perpustakaan kelas sebagai pakej.

Artikel ini meneroka pakej; Saya menunjukkan kepada anda cara membuat pakej kelas dan antara muka, cara mengimport (iaitu, masuk ke dalam program) kelas dan antaramuka yang dibungkus, cara memindahkan pakej pada cakera keras, dan bagaimana menggunakan fail jar untuk merangkum pakej.

Catatan
Eksperimen pakej tunggal artikel ini adalah khusus Microsoft Windows. Anda semestinya dapat memperhebatkan eksperimen ini dengan mudah ke platform bukan Windows.

Apa itu pakej?

A pakej adalah koleksi kelas dan antara muka. Setiap pakej mempunyai namanya sendiri dan mengatur kelas dan antaramuka tingkat atas (iaitu, tidak bersarang) ke ruang nama atau koleksi nama yang terpisah . Walaupun kelas dan antaramuka yang sama tidak dapat muncul dalam pakej yang sama, mereka dapat muncul dalam pakej yang berbeza kerana ruang nama yang terpisah diberikan untuk setiap pakej.

Dari perspektif pelaksanaan, menyamakan paket dengan direktori terbukti bermanfaat, begitu juga dengan menyamakan kelas dan antara muka paket dengan classfiles direktori. Ingatlah pendekatan lain - seperti penggunaan pangkalan data - untuk melaksanakan pakej, jadi jangan terbiasa selalu menyamakan pakej dengan direktori. Tetapi kerana banyak JVM menggunakan direktori untuk melaksanakan pakej, artikel ini menyamakan pakej dengan direktori. Java 2 SDK mengatur koleksi kelas dan antaramuka yang luas menjadi hierarki pokok seperti pakej dalam pakej, yang setara dengan direktori dalam direktori. Hierarki itu membolehkan Sun Microsystems mengedarkan (dan anda dapat bekerja dengan mudah) kelas dan antara muka tersebut dengan mudah. Contoh pakej Java termasuk:

  • java.lang:Kumpulan kelas yang berkaitan dengan bahasa, seperti Objectdan String, diatur dalam sub java-paket pakejlang
  • java.lang.ref:Himpunan kelas bahasa rujukan yang berkaitan, seperti SoftReferencedan ReferenceQueue, yang dianjurkan dalam refsub-subpakej daripada javapakej ini langsubpakej
  • javax.swing:Kumpulan kelas komponen yang berkaitan dengan Swing, seperti JButton, dan antaramuka, seperti ButtonModel, yang disusun dalam subpakej javaxpakejswing

Watak noktah memisahkan nama pakej. Contohnya, dalam javax.swing, watak noktah memisahkan nama pakej javaxdari nama subpakej swing. Karakter noktah adalah setara bebas platform dengan watak slash ke depan ( /), watak garis miring terbalik ( \), atau watak lain untuk memisahkan nama direktori dalam pelaksanaan pakej berasaskan direktori, cabang pangkalan data dalam pelaksanaan pakej berasaskan pangkalan data hierarki, dan sebagainya. .

Petua
Sama seperti anda tidak dapat menyimpan fail dan direktori dengan nama yang sama dalam direktori yang sama, anda tidak boleh menyimpan kelas atau antara muka dan pakej dengan nama yang sama dalam pakej yang sama. Sebagai contoh, memandangkan pakej bernama accounts, anda tidak boleh menyimpan pakej dan kelas yang dinamakan payabledalam accounts. Untuk mengelakkan nama yang bertentangan, huruf besar huruf pertama kelas dan nama antara muka, dan huruf kecil nama pakej pertama. Dengan menggunakan contoh sebelumnya, simpan kelas Payabledalam pakej accountssebagai accounts.Payabledan pakej payabledalam pakej accountssebagai accounts.payable. Ketahui lebih lanjut mengenai ini dan konvensyen penamaan lain dari Konvensyen Kod Sun untuk Bahasa Pengaturcaraan Java .

Buat pakej kelas dan antara muka

Setiap kelas dan antara muka fail sumber disusun dalam satu pakej. Dalam packageketiadaan arahan, kelas dan antara muka tersebut termasuk dalam paket yang tidak disebutkan namanya (direktori yang dianggap JVM sebagai direktori semasa — direktori di mana program Java memulakan pelaksanaannya melalui program Windows java.exe, atau setara dengan OS - dan tidak berisi sub-paket) . Tetapi jika packagearahan itu muncul dalam fail sumber, arahan itu memberi nama paket untuk kelas dan antara muka tersebut. Gunakan sintaks berikut untuk menentukan packagearahan dalam kod sumber:

'package' packageName ['.' subpackageName ...] ';'

A packagearahan bermula dengan packagekata kunci. Pengecam yang menamakan paket packageName, akan segera diikuti. Sekiranya kelas dan antara muka muncul dalam sub-paket (pada tahap tertentu) dalam packageName, satu atau lebih subpackageNamepengecam yang dipisahkan tempoh akan muncul selepasnya packageName. Fragmen kod berikut menunjukkan sepasang packagearahan:

permainan pakej; permainan pakej.devices;

packageArahan pertama mengenal pasti pakej yang dinamakan game. Semua kelas dan antara muka yang terdapat dalam fail sumber arahan itu disusun dalam gamepakej. packageArahan kedua mengenalpasti sub-paket yang diberi nama devices, yang berada dalam pakej yang dinamakan game. Semua kelas dan antara muka yang terdapat dalam fail sumber arahan itu disusun dalam subpakej gamepakej devices. Sekiranya pelaksanaan JVM memetakan nama pakej ke nama direktori, game.devicespeta ke game\deviceshierarki direktori di bawah Windows dan game/deviceshierarki direktori di bawah Linux atau Solaris.

Awas
Hanya satu packagearahan yang boleh muncul dalam fail sumber. Selanjutnya, packagearahan mestilah kod pertama (selain dari komen) dalam fail tersebut. Melanggar salah satu peraturan menyebabkan penyusun Java melaporkan kesalahan.

Untuk membantu anda merasa selesa dengan pakej, saya telah menyediakan contoh yang merangkumi semua topik dalam artikel ini. Di bahagian ini, anda belajar bagaimana membuat pakej contoh. Di bahagian kemudian, anda akan belajar cara mengimport kelas dan antara muka dari pakej ini, cara memindahkan pakej ini ke lokasi lain di cakera keras anda dan masih mengakses pakej dari program, dan bagaimana menyimpan pakej dalam fail jar . Penyenaraian 1 menunjukkan kod sumber pakej:

Penyenaraian 1. A.java

// pakej A.java testpkg; kelas awam A {int x = 1; int awam y = 2; int z = 3 yang dilindungi; int returnx () {pulangan x; } int kembali awam () {return y; } dilindungi int returnz () {return z; } antara muka awam StartStop {void start (); berhenti kosong (); }} kelas B {public static void hello () {System.out.println ("hello"); }}

Penyenaraian 1 memperkenalkan kod sumber untuk pakej bernama pertama anda. Yang package testpkg;nama arahan pakej testpkg. Di dalamnya testpkgterdapat kelas Adan B. Di Adalamnya terdapat tiga deklarasi lapangan, tiga deklarasi kaedah, dan deklarasi antara muka. Di dalamnya Bterdapat satu deklarasi kaedah. Keseluruhan kod sumber disimpan A.javakerana Akelas awam. Tugas kami: Ubah kod sumber ini menjadi pakej yang terdiri daripada dua kelas dan antara muka dalaman (atau direktori yang mengandungi tiga classfiles). Langkah-langkah khusus Windows berikut menyelesaikan tugas itu:

  1. Open a Windows command window and ensure you are in the c: drive's root directory (the main directory—represented by an initial backslash (\) character). To do that, type the c: command followed by the cd \ command. (If you use a different drive, replace c: with your chosen drive. Also, do not forget to press the Enter key after typing a command.)
  2. Create a testpkg directory by typing md testpkg. Note: When following this article's steps, do not type periods after the commands.
  3. Make testpkg the current directory by typing cd testpkg.
  4. Use an editor to enter Listing 1's source code and save that code to an A.java file in testpkg.
  5. Compile A.java by typing javac A.java. You should see classfiles A$StartStop.class, A.class, and B.class appear in the testpkg directory.

Figure 1 illustrates Steps 3 through 5.

Congratulations! You have just created your first package. Think of this package as containing two classes (A and B) and A's single inner interface (StartStop). You can also think of this package as a directory containing three classfiles: A$StartStop.class, A.class, and B.class.

Note
To minimize package name conflicts (especially among commercial packages), Sun has established a convention in which a company's Internet domain name reverses and prefixes a package name. For example, a company with x.com as its Internet domain name and a.b as a package name (a) followed by a subpackage name (b) prefixes com.x to a.b, resulting in com.x.a.b. My article does not follow this convention because the testpkg package is a throw-away designed for teaching purposes only.

Import a package's classes and interfaces

Once you have a package, you will want to import classes and/or interfaces—actually, class and/or interface names—from that package to your program, so it can use those classes and/or interfaces. One way to accomplish that task is to supply the fully qualified package name (the package name and all subpackage names) in each place where the reference type name (the class or interface name) appears, as Listing 2 demonstrates:

Listing 2. Usetestpkg1.java

// Usetestpkg1.java class Usetestpkg1 implements 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 = new Usetestpkg1 (); utp.start (); utp.stop (); } public void start () { System.out.println ("Start"); } public void stop () { System.out.println ("Stop"); } } 

By prefixing testpkg. to A, Usetestpkg1 accesses testpkg's class A in two places and A's inner interface StartStop in one place. Complete the following steps to compile and run Usetestpkg1:

  1. Open a Windows command window and make sure you are in the c: drive's root directory.
  2. Ensure the classpath environment variable does not exist by executing set classpath=. (I discuss classpath later in this article.)
  3. Use an editor to enter Listing 2's source code and save that code to a Usetestpkg1.java file in the root directory.
  4. Compile Usetestpkg1.java by typing javac Usetestpkg1.java. You should see classfile Usetestpkg1.class appear in the root directory.
  5. Type java Usetestpkg1 to run this program.

Figure 2 illustrates Steps 3 through 5 and shows the program's output.

According to Usetestpkg1's output, the main() method's thread successfully accesses testpkg.A's y field and calls the returny() method. Furthermore, the output shows a successful implementation of the testpkg.A.StartStop inner interface.

For Usetestpkg1, prefixing testpkg. to A in three places doesn't seem a big deal. But who wants to specify a fully qualified package name prefix in a hundred places? Fortunately, Java supplies the import directive to import a package's public reference type name(s), so you do not have to enter fully qualified package name prefixes. Express an import directive in source code via the following syntax:

'import' packageName [ '.' subpackageName ... ] '.' ( referencetypeName | '*' ) ';' 

An import directive consists of the import keyword immediately followed by an identifier that names a package, packageName. An optional list of subpackageName identifiers follows to identify the appropriate subpackage (if necessary). The directive concludes with either a referencetypeName identifier that identifies a specific class or interface from the package, or an asterisk (*) character. If referencetypeName appears, the directive is a single-type import directive. If an asterisk character appears, the directive is a type-on-demand import directive.

Caution
As with the package directive, import directives must appear before any other code, with three exceptions: a package directive, other import directives, or comments.

The single-type import directive imports the name of a single public reference type from a package, as the following code fragment demonstrates:

import java.util.Date; 

The previous single-type import directive imports class name Date into source code. As a result, you specify Date instead of java.util.Date in each place that class name appears in source code. For example, when creating a Date object, specify Date d = new Date (); instead of java.util.Date d = new java.util.Date ();.

Berhati-hati dengan importarahan jenis tunggal . Sekiranya penyusun mengesan importarahan jenis tunggal yang menentukan nama jenis rujukan yang juga dinyatakan dalam fail sumber, penyusun melaporkan ralat, seperti yang ditunjukkan oleh fragmen kod berikut:

import java.util.Date; Tarikh kelas {}

Penyusun menganggap fragmen kod sebagai usaha untuk memperkenalkan dua jenis rujukan dengan Datenama yang sama :