Jika kita memanggil metode getPackage pada objek kelas, kita bisa mendapatkan objek paket yang menggambarkan paket di mana kelas berada (kelas paket didefinisikan dalam java.lang). Kami juga dapat menggunakan nama paket untuk mendapatkan objek paket dengan memanggil metode statis getPackage atau memanggil metode getpackage statis (yang mengembalikan array yang terdiri dari semua paket yang diketahui dalam sistem). Metode GetName dapat mengembalikan nama lengkap paket.
Penggunaan objek paket benar -benar berbeda dari jenis refleksi lainnya, yaitu kita tidak dapat membuat atau memanipulasi paket saat runtime. Kami dapat menggunakan objek paket untuk mendapatkan informasi tentang paket, seperti tujuan paket, yang membuat paket, versi paket, dll. Kami akan menunda konten ini sampai kami akan membahasnya secara rinci nanti.
Penamaan paket
Nama paket harus menghindari konflik dengan paket lain, jadi memilih nama yang bermakna dan unik adalah aspek penting dari desain paket. Namun, pemrogram di seluruh dunia sedang mengembangkan paket, dan tidak ada cara untuk mengetahui siapa yang menggunakan nama paket apa, jadi memilih satu -satunya nama paket adalah masalah. Jika kami menentukan bahwa suatu paket hanya digunakan dalam organisasi kami, kami dapat memiliki wasit internal untuk memastikan bahwa tidak ada konflik nama antar proyek.
Tetapi bagi seluruh dunia, pendekatan ini tidak praktis. Pengidentifikasi paket adalah semua nama sederhana, dan cara yang lebih baik untuk memastikan bahwa nama paket adalah menggunakan nama domain internet. Jika perusahaan tempat kami bekerja adalah Magic.lnc dan nama domain perusahaan adalah Magic C.com, maka deklarasi paket atribut harus:
paket com.magic.attr;
Perhatikan bahwa nama konstituen nama domain di sini diatur dalam urutan terbalik dari nama domain konvensional.
Jika kami mengadopsi idiom ini, nama paket yang kami gunakan tidak akan bertentangan dengan orang lain kecuali kemungkinan konflik dalam organisasi kami. Jika memang ada konflik dalam organisasi kami (mungkin perusahaan besar), maka kami dapat menggunakan nama domain yang lebih spesifik untuk memenuhi syarat lebih lanjut. Banyak perusahaan besar memiliki subdomain internal, seperti Timur dan Eropa, yang dapat digunakan untuk lebih memenuhi syarat nama paket:
paket jagung.magic.japan.attr;
Menggunakan solusi ini dapat membuat nama paket sangat lama, tetapi relatif aman. Pemrogram yang menggunakan teknik ini tidak akan memilih nama paket yang sama, dan pemrogram yang tidak menggunakan teknik ini tidak akan memilih nama yang kami gunakan.
Konten paket
Isi paket harus dirancang dengan cermat sehingga mereka hanya menyertakan kelas dan antarmuka yang relevan secara fungsional. Kelas dalam paket dapat dengan bebas mengakses anggota non-pribadi dari kelas lain dalam paket, dan beberapa kelas bahkan mungkin memiliki izin yang cukup untuk mengakses rincian internal kelas lain. Untuk menghindari kelas seperti itu dari anggota kelas yang salah, kita perlu melindungi anggota kelas. Setiap anggota yang tidak dinyatakan sebagai pribadi dapat diakses oleh semua jenis lain dalam paket yang sama, sehingga setiap kelas yang tidak terkait mungkin lebih cenderung lebih terkoordinasi daripada yang kita harapkan.
Paket juga menyediakan pengelompokan logis untuk programmer yang mencari antarmuka dan kelas yang berguna. Paket yang terdiri dari kelas yang tidak relevan menyulitkan pemrogram untuk mengetahui antarmuka dan kelas mana yang berguna, dan pengelompokan kelas yang logis dapat membantu pemrogram menggunakan kembali kode karena pemrogram dapat menemukan apa yang mereka butuhkan dengan lebih mudah melalui pengelompokan logis. Jika paket hanya berisi set tipe terkait yang erat, itu berarti bahwa kita dapat memberikan tipe beberapa nama yang lebih intuitif untuk menghindari konflik nama.
Paket bisa bersarang. Misalnya, java.lang adalah paket bersarang di mana paket lang bersarang dalam paket java yang lebih besar, sedangkan paket j ava juga berisi beberapa paket lainnya. Nesting membuat paket terkait membentuk sistem penamaan dengan struktur hierarkis.
Misalnya, untuk membuat serangkaian paket untuk sistem adaptif seperti jaringan saraf dan algoritma genetika, kami dapat menyebutkan nama paket dengan nama yang dipisahkan dot untuk membuat paket bersarang:
paket adaptif. jaring saraf;
File sumber yang berisi pernyataan deklarasi di atas terletak di paket adaptif.neuralnet, dan paket adaptif.neuralnet itu sendiri adalah subpackage dari paket adaptif. Paket adaptif mungkin berisi beberapa kelas yang terkait dengan algoritma adaptif umum, seperti kelas pernyataan masalah generalisasi atau kelas benchmark. Paket yang berada dalam posisi yang lebih dalam dalam hierarki (misalnya adaptif.neu-ralnet atau adaptif.genetic) berisi kelas yang terkait dengan jenis algoritma adaptif tertentu.
Sarang paket hanyalah alat untuk mengatur paket terkait, dan tidak memberikan hak akses khusus antar paket.
Kode kelas dalam paket adaptif. Paket genetik tidak dapat mengakses anggota dalam paket adaptif atau adaptif.neuralnet yang memiliki hak akses paket, dan ruang lingkup paket hanya berlaku untuk paket tertentu. Sarang paket dapat mengelompokkan paket yang relevan dan membantu pemrogram menemukan kelas yang diinginkan di tingkat logis lebih nyaman, tetapi di luar itu, itu tidak membawa manfaat lain.
Catatan paket
Paket ini juga dapat memiliki anotasi. Tetapi masalahnya adalah bahwa karena paket adalah struktur organisasi tanpa entitas kode sumber dan mereka tidak memiliki definisi aktual, mereka tidak dapat dijelaskan seperti kelas atau metode, sehingga anotasi paket hanya dapat dicapai dengan anotasi pernyataan deklarasi paket dalam file sumber. Namun, hanya ada satu deklarasi paket di setiap paket yang dapat memiliki anotasi yang bertindak di atasnya.
Jadi, bagaimana Anda membuat anotasi paket? Faktanya, Java tidak memaksa programmer untuk menggunakan beberapa cara untuk menangani aturan "pernyataan paket beranotasi tunggal". Cara yang disarankan adalah dengan membuat file bernama paket-i nfo.java di direktori paket, di mana hanya pernyataan paket dan anotasi paket yang disimpan tanpa menempatkan yang lain. Misalnya, file package info.java untuk paket attr terlihat seperti ini:
@PackageSpec (nama dua "proyek attr", version = "1.0" @developmentite ("attr.project.org") @DevelopmentModel ("open-source") Paket ATTR;PackageSpec, Developmentite dan pengembangan OpmentModel digunakan untuk memodifikasi jenis anotasi. Tentu saja, mereka memiliki strategi penghematan runtime. File paket-info.java harus dikompilasi dengan file sumber lain dalam paket.
Kami merekomendasikan menempatkan semua informasi terkait paket dalam file package-info.java. Jika Anda melakukan ini, Anda dapat menempatkan komentar dokumen di awal file, sehingga dokumen -dokumen ini dijelaskan sebagai dokumen paket.
Akses Paket
Saat menyatakan aksesibilitas kelas tingkat atas dan antarmuka tingkat atas dalam paket, ada dua opsi: akses paket (paket) dan akses publik (publik). Kelas atau antarmuka yang dimodifikasi dengan publik dapat diakses dengan kode out-of-package, sementara jenis yang tidak dihiasi dengan publik memiliki ruang lingkup paket: mereka dapat diakses dengan kode lain dalam paket yang sama; Tetapi mereka disembunyikan untuk kode out-of-package, bahkan dalam kode subpackage. Saat mendeklarasikan jenis, kita hanya boleh menyatakan jenis -jenis yang perlu digunakan oleh pemrogram lain sebagai publik, dan menyembunyikan jenis -jenis yang dimiliki oleh detail implementasi paket. Teknologi ini memberi kita fleksibilitas yang luar biasa, dan karena pemrogram tidak mengandalkan jenis detail implementasi yang tidak dapat mereka akses, kita dapat dengan bebas mengubahnya ketika kita ingin mengubah detail implementasi.
Anggota kelas yang tidak dinyatakan sebagai publik, terlindungi atau pribadi dapat diakses secara langsung dengan kode apa pun di dalam paket, tetapi disembunyikan dari luar paket. Dengan kata lain, pengubah akses default adalah "paket", dengan pengecualian anggota antarmuka, dan pengubah akses default mereka adalah "publik".
Bidang atau metode yang tidak dinyatakan pribadi dalam suatu paket dapat diakses oleh semua kode lain dalam paket itu, sehingga kelas dalam paket yang sama dianggap "ramah" atau "tepercaya". Ini memungkinkan kami untuk mendefinisikan kerangka kerja aplikasi yang menggabungkan kode yang telah ditentukan dan kode placeholder, di mana kode placeholder ditimpa oleh subclass dari kelas kerangka kerja. Kode yang telah ditentukan dapat menggunakan pengubah akses paket sehingga kode kolaboratif lain dalam paket dapat secara langsung mengaksesnya, tetapi untuk pengguna di luar paket, kode-kode ini tidak dapat diakses. Namun, subpackage dari paket di mana kode -kode ini berada tidak tepercaya dan sebaliknya. Misalnya, kode yang dimodifikasi dengan pengubah akses paket dalam paket DIT tidak dapat diakses oleh kode dalam paket anaknya dit.dat, dan sebaliknya.
Oleh karena itu, masing -masing jenis mendefinisikan tiga kontrak yang berbeda:
.publi. Kontrak: Menentukan fungsi utama jenis.
Kontrak yang dilindungi: Menentukan fungsi yang tersedia untuk subkelas untuk tujuan spesialisasi.
Kontrak .Package: Menentukan fungsi yang dapat diperoleh dengan kode lain dalam paket untuk mencapai kolaborasi antar jenis dalam paket. Semua kontrak ini membutuhkan pertimbangan dan desain yang cermat.
Metode aksesibilitas dan penutup
Hanya metode yang dapat diakses dalam superclass yang dapat ditimpa di subkelas. Jika metode dalam superclass tidak dapat diakses, metode ini tidak dapat diganti dalam subkelas bahkan jika metode dalam subkelas memiliki nama yang sama dengan metode tersebut. Ketika metode dipanggil saat runtime, sistem mempertimbangkan aksesibilitasnya dan dengan demikian menentukan implementasi mana yang sedang berjalan.
Contoh yang dibangun secara khusus dijelaskan lebih jelas. Misalkan kami mendeklarasikan kelas basis abstrak dalam paket P1:
paket p1; {Ab abab abab kelas abstrak abstrak abstrak private void pri () {print ("stractbase.pri ()"):} void pac () {print ("stractbase.pac ()"); } protected void pro () {print ("stractbase.pro ()"); } public void pub () {print ("stractbase.pub ()");} public final void show () pri (); Pac (); pro(); pub (); }}Di kelas ini, kami mendefinisikan 4 metode, masing -masing dengan pengubah akses yang berbeda, dan tubuh metode ini hanya mengidentifikasi dirinya sendiri. Metode ini menunjukkan panggilan 4 metode ini pada objek saat ini secara bergantian. Saat menerapkan metode ini ke berbagai objek subkelas, itu dapat menjelaskan implementasi metode ini yang disebut.
Sekarang, kami mendefinisikan Class Concretel, yang memperluas kelas AbstractBase, tetapi terletak di paket P2:
paket p2; Impor P1.ABSTRACTBASE PUBLIK PUBLIK CONCRETEL Memperluas AbstractBase {public void pri () {print ("concretel.pri ()");} public void pac () {print ("concretel.pac ()");} public void pro () {print ("concretel.pro ()"); pub () {print ("concretel.pub ()");}}4 Metode dalam superclass dirapisi ulang di kelas ini dan implementasinya diubah, yang melaporkan bahwa mereka termasuk kelas con-cretel. Pada saat yang sama, hak akses mereka telah diubah menjadi publik untuk diakses kode lain. Menjalankan kode berikut
concretel baru (). show ():
Output berikut akan dihasilkan:
AbstractBase.pri () AbstractBase.pac () CONCRETEL.PRO () CONCRETEL.PUB ()
Karena metode pribadi PRI tidak dapat diakses oleh subkelas (atau kelas lain), metode show selalu menyebut implementasi metode PRI di kelas AbstractBase. Metode PAC dengan izin akses paket di kelas AbstractBase tidak dapat diakses oleh Concretel, sehingga implementasi metode PAC di kelas Concretel tidak dapat mengganti definisi di kelas AbstractBase, sehingga metode acara menyebut metode AbstractBase.PAC. Metode Pro dan metode PUB keduanya dapat diakses di kelas Concretel dan juga dapat ditimpa, sehingga metode acara menyebut implementasi kedua metode ini di kelas Concretel.
Ikuti Kaki Kaki Kami Makna Class Concrete2 untuk memperluas Class Concretel, dan kemudian kami meletakkannya di paket yang sama P1 dengan kelas AbstractBase ':
paket p1; Impor P2.Conscretel Public Class Concrete2 Memperluas Concretel {public void pri () {print ("concrete2.pri ()");} public void pac () {print ("concrete2.pac ()");} public void pro () {print ("concrete2.pro () (); }Karena metode di Concretel memiliki hak akses publik, mereka dapat diakses di Concrete2, dan setiap metode dalam Concrete2 mencakup metode yang sesuai secara terpisah. Selain itu, karena Concrete2 dan AbstractBase berada dalam paket yang sama, metode AbstractBase.pac juga dapat diakses di Concrete2, dan metode Concrete2.pac dapat ditimpa. Panggil metode show pada objek Concrete2, dan hasil cetak adalah sebagai berikut:
Abstractbase.pri () concrete2.pac () concrete2.pro () concrete2.pub ()
Akhirnya, kami mendefinisikan Class Concrete3 untuk memperpanjang kelas Conon2 dan memasukkannya ke dalam paket P3:
Paket P3 Impor P1.concrete2; Kelas publik CONCRETE3 memperluas CONCRETE2 {public void pri () {print ("concrete3.pri ()");} public void Pac q {print ("concrete3.pac ()");} public void pro () {print ("concrete) ()");} pub pub publik () {cetak ("CONCRETE3.PRO ()");Hubungi metode show pada objek Concrete3, dan hasil cetak adalah sebagai berikut:
AbstractBase.pri () concrete3.pac () concrete3.pro () concrete3.pub ()
Di sini metode CONCRETE3.PAC sepertinya mengesampingkan metode abstractbase.pac yang tidak dapat diakses, tetapi pada kenyataannya, metode Concrete3.pac menimpa metode CONCRETE2.PAC, dan metode CONCRETE2.PAC mengesampingkan metode abstractbase.pac, jadi metode CONCRETE3.PAC secara tidak langsung mengesampingkan metode abstrak.pac. Dengan mereduksi ulang metode PAC di kelas Concrete2 sebagai memiliki izin akses publik, dapat diakses dan ditimpa oleh subkelas mana pun.
Paket objek dan spesifikasi
Paket biasanya menerapkan beberapa spesifikasi, dan biasanya dari suatu organisasi. Objek paket berbeda dari tipe refleksi lain dan tidak dapat digunakan untuk membuat atau mengoperasikan paket, tetapi hanya dapat berfungsi sebagai basis pengetahuan untuk memberikan informasi, yang memberikan informasi tentang spesifikasi yang diimplementasikan oleh paket (judul, vendor, dan nomor versi) dan informasi tentang implementasi paket itu sendiri (judul, vendor, dan nomor versi paket). Meskipun paket biasanya berasal dari organisasi individu, spesifikasi yang diterapkannya (seperti pustaka analisis statistik) dapat didefinisikan oleh organisasi lain. Program yang menggunakan paket mungkin perlu mengetahui versi spesifikasi yang diimplementasikan oleh paket, sehingga fungsi yang hanya ditentukan dalam versi tertentu dapat digunakan. Demikian pula, program -program ini mungkin juga perlu mengetahui versi implementasi mana yang disediakan untuk itu, terutama untuk menangani kemungkinan kekurangan dalam versi yang berbeda. Beberapa metode utama kelas paket memungkinkan akses ke informasi ini:
・ GetName publik (): Mengembalikan nama paket.
.public String getSpecificationTitle p: Mengembalikan judul spesifikasi yang diimplementasikan oleh paket. Jika judulnya tidak diketahui, kembalikan nol,
.public String getSpecificationVersion (): Mengembalikan string yang menjelaskan informasi versi spesifikasi yang diimplementasikan oleh paket. Jika informasi versi tidak diketahui, kembalikan nol,
.public String getSpecification vendor T: Mengembalikan nama pemasok, yang memiliki dan mempertahankan spesifikasi yang diimplementasikan oleh paket. Jika pemasok tidak diketahui, kembalikan nol,
.public string getImplerentationTitle (): Mengembalikan judul implementasi yang disediakan oleh paket. Jika judulnya tidak diketahui, ia mengembalikan NULL, ・ Publik GetImlementationVersion (): Mengembalikan string yang menjelaskan informasi versi implementasi yang disediakan oleh paket. Jika informasi versi tidak diketahui, ia mengembalikan nol,
・ String publik getImplementationVendor (): Mengembalikan nama organisasi (vendor) yang menyediakan implementasi. Jika organisasi tidak diketahui, kembalikan nol,
Misalnya, jika kami mengekstrak informasi ini dari paket java.lang di sistem kami, kami akan mendapatkan hasil berikut:
Judul Spesifikasi: Java Platform API Spesifikasi Spesifikasi Versi: 1.4 Vendor Spesifikasi: Sun Microsystems, Inc. Judul Implementasi: Java Runtime Environment Versi Implementasi: 1.5.0_02 Implementasi Vendor: Sun Microsystems, Inc.
Nomor versi kanonik terdiri dari angka non-negatif yang dipisahkan oleh pembatas periode, seperti '' 2.0 'atau '11 .0.12'. Pola ini memungkinkan kita untuk memanggil metode ISCompatiblewith untuk membandingkan nomor versi yang mengikuti pola ini dengan nomor versi paket. Jika nomor versi paket lebih besar dari atau sama dengan nomor versi penerus, maka metode ini mengembalikan true. Perbandingan ini hanya membandingkan angka yang dipisahkan periode sekaligus. Jika salah satu dari angka -angka ini lebih kecil dari posisi yang sesuai dalam nomor versi yang diteruskan, maka kedua versi tersebut tidak kompatibel. Jika salah satu nomor versi lebih panjang dari yang lain, bagian yang hilang dalam nomor versi pendek akan dianggap nol. Misalnya, jika nomor versi kanonik paket adalah "1.4" dan kami membandingkannya dengan "1.2", "1.3.1 '. Atau" .1.81., Maka true akan dikembalikan; tetapi jika dibandingkan dengan "1.4.2 '. Atau" .5 ", maka false akan dikembalikan. Kesimpulan ini ditarik karena mekanisme perbandingan ini mengasumsikan bahwa versi spesifikasi kompatibel ke belakang.
Tidak ada format yang ditentukan untuk nomor versi implementasi, karena berbagai organisasi yang menyediakan implementasi akan menentukan versi implementasi secara berbeda. Satu -satunya perbandingan yang dapat dibuat antara versi implementasi adalah untuk menguji apakah versi tersebut sama, di mana tidak ada asumsi kompatibilitas mundur.
Paket dapat disegel, yang berarti bahwa kelas tidak dapat lagi ditambahkan ke paket. Paket yang tidak disegel dapat berisi kelas -kelas dari beberapa lokasi yang berbeda di jalur pencarian kelas, sedangkan isi paket yang disegel harus berasal dari lokasi yang sama - baik arsip tertentu atau lokasi yang ditentukan oleh URL. Ada dua cara untuk menentukan apakah suatu paket disegel:
.Public Boolean ISSEALED P: kembalikan trueo jika paket disegel
.Public Boolean Issealed (URL URL): Kembalikan true jika paket disegel untuk URL yang diberikan, yaitu, kelas dalam paket dapat dimuat dari URL yang diberikan ini. Jika kelas dalam paket tidak dapat dimuat dari URL yang diberikan, atau paket tidak disegel, maka false dikembalikan, dan spesifikasi dan informasi implementasi paket biasanya disediakan sebagai bagian dari file manifes yang disimpan dengan paket - misalnya sebagai bagian dari file manifes dalam arsip Java (JAR), seperti dijelaskan dalam bagian 25.9.2, “Archive File JAVA.J.JA. Ketika kelas dalam suatu paket dimuat, informasi ini dibaca oleh orang tersebut. ClassLoader dapat secara dinamis mendefinisikan objek paket untuk kelas yang ingin dimuat:
. Denepackage Paket yang Diproteksi (Nama String, String Spectitle, String Specversion, String Specvendor, String ImplTitle, String Implversion, String Impvendor, URL Sealbase): Metode ini akan mengembalikan objek paket dengan nama paket yang diberikan dan nilai spesifikasi dan implementasi yang ditetapkan oleh penawaran yang sesuai. Jika parameter sealbase adalah nol, maka paket tidak disegel, jika tidak paket disegel untuk URL ini: Objek paket kelas harus ditentukan sebelum kelas ditentukan, dan nama paket harus unik di loader kelas. Jika nama paket diulangi dengan nama yang ada, karya 11Ega1ArgumentException akan dilemparkan.
Kita dapat memanggil metode getPackage dari objek kelas dari kelas yang diberikan untuk mendapatkan objek paket kelas ini. Kami juga dapat menghubungi paket statis.getPackage dengan nama paket yang diberikan untuk mendapatkan objek paket, atau menghubungi paket statis.getPackages, yang akan mengembalikan array paket yang terdiri dari semua paket yang saat ini diketahui oleh class loader. Kedua metode ini terkait dengan loader kelas yang memanggil kode mereka, karena kode-kode ini akan memanggil metode get-package atau getPackages dari loader kelas mereka. Metode loader kelas ini akan mencari loader kelas tertentu dan semua loader kelas induknya, dan jika tidak ada pengaturan yang dibuat untuk loader kelas saat ini, loader kelas sistem akan digunakan saat ini. Perhatikan bahwa jika paket tidak diketahui, metode ClassLoader akan mengembalikan NULL karena tidak ada jenis dalam paket yang telah dimuat saat ini.