Soalan dan skop
Selepas menaik taraf kepada Java 25, sebuah pasukan mahukan fail sumber padat untuk utiliti kecil. Terangkan pemilihan titik masuk, ahli bagi kelas yang diisytiharkan secara tersirat, sempadan import automatik, dan cara anda memutuskan sama ada untuk mengguna pakai ciri ini dalam pengeluaran.
JEP 512 memuktamadkan Fail Sumber Padat dan Kaedah Main Contoh selepas keluaran pratonton. Sebuah fail boleh meniadakan pengisytiharan kelas peringkat teratas; medan, kaedah, dan pengisytiharan bersarang peringkat teratas menjadi ahli bagi kelas yang diisytiharkan secara tersirat, manakala pelancar masih mengikut protokol yang ditetapkan untuk mencari kaedah main yang boleh dilancarkan.
Perkara yang diuji oleh penemu duga
Kupas model kelas sebenar di sebalik gula sintaksis bahasa ini, perbezaan antara titik masuk tanpa hujah dan hujah tatasusunan, import atas permintaan java.base dan sempadan IO, arahan kompilasi dan larian, had dokumentasi dan penyahpepijatan, serta strategi penerimaan beransur-ansur.
Jawapan 30 saat
“Saya akan meletakkan ciri ini sebagai pengurangan kod berulang (boilerplate) untuk skrip fail tunggal, contoh pengajaran, dan alatan sekali guna. Pengkompil mengisytiharkan kelas yang memperluaskan Object secara tersirat; ahli peringkat teratas menjadi ahlinya. Pelancar terlebih dahulu memilih void main(String[]) yang boleh diakses dan jika tiada, memilih void main() yang boleh diakses; titik masuk contoh dipanggil selepas pembina lalai berjalan. Java 25 mengimport jenis peringkat teratas awam yang dieksport oleh java.base atas permintaan, tetapi kaedah statik IO tidak diimport secara tersirat. Saya akan mengekalkan kelas eksplisit untuk pustaka awam dan perkhidmatan kompleks, sambil mengesahkan JDK sasaran, alat binaan, dan saluran paip dokumentasi terlebih dahulu.”
Penyelesaian langkah demi langkah
Langkah 1: Kenal pasti kelas yang diisytiharkan secara tersirat
Fail sumber tanpa pengisytiharan kelas yang melingkupinya mengisytiharkan kelas secara tersirat. Ia memperluaskan Object, mempunyai pembina tanpa hujah yang lalai, dan menerima nama pilihan hos yang tidak boleh dirujuk secara langsung oleh kod sumber lain. Medan, kaedah, dan pengisytiharan bersarang dalam fail tersebut menjadi ahli bagi kelas itu.
Langkah 2: Tentukan titik masuk yang boleh dilancarkan
Pelancar terlebih dahulu mencari void main yang boleh diakses dengan parameter tatasusunan String. Jika tiada, ia mencari void main yang boleh diakses tanpa sebarang parameter. Apabila kaedah yang dipilih ialah kaedah contoh, pelancar membina contoh bagi kelas tersirat tersebut sebelum memanggilnya.
void main(String[] args) {
IO.println("hello " + args[0]);
}Langkah 3: Fahami import automatik
Fail sumber padat bertindak seolah-olah ia mengimport jenis peringkat teratas awam yang dieksport oleh java.base atas permintaan, jadi jenis seperti Map dan Stream biasanya tidak memerlukan import eksplisit. Ini tidak mengimport modul sewenang-wenangnya, dan kaedah statik IO tidak diimport secara tersirat; panggil IO.println atau tambahkan import statik eksplisit.
Langkah 4: Bezakan mod larian dan kompilasi
Anda boleh menjalankan java Hello.java, membenarkan pelancar mengkompilasi dan melaksanakan fail tersebut, atau menjalankan javac Hello.java diikuti oleh kelas yang dijana. Pelaksanaan sumber secara langsung adalah mudah untuk skrip pendek; binaan yang boleh diulang, pencirian cache, dan saluran paip keluaran masih perlu dikompilasi secara eksplisit ke dalam direktori output yang diketahui.
Langkah 5: Analisis keadaan dan kitaran hayat
Medan peringkat teratas menjadi medan bagi kelas tersirat, jadi main contoh boleh membaca keadaan contoh. Pelancar menggunakan pembina lalai, jadi suntikan hujah pembina luaran bukan sebahagian daripada protokol ini. Pengawalan kompleks, berbilang titik masuk, atau kitaran hayat eksplisit lebih mudah disemak dalam kelas yang dinamakan.
Langkah 6: Nilaikan sempadan alatan
Kelas yang diisytiharkan secara tersirat tidak mempunyai nama peringkat sumber yang stabil untuk dirujuk oleh kelas lain, dan javadoc tidak dapat menjana API konvensional untuknya. IDE, penganalisis statik, alat liputan, dan penyahpepijat mungkin menyokong sintaks ini pada versi yang berbeza; sahkan JDK sasaran dan pemalam binaan bersama-sama.
Langkah 7: Reka bentuk migrasi dan pengembalian
Pindahkan skrip atau contoh pengajaran ke dalam direktori berasingan terlebih dahulu dan simpan versi kelas eksplisit sebagai pengembalian (rollback). Tetapkan Java 25 dalam CI, periksa sama ada versi java dan javac sepadan, serta sahkan pembungkusan, log, surihan pengecualian, dan arahan kontena tidak bergantung pada nama kelas pelaksanaan.
Langkah 8: Tentukan sempadan penerimaan
Penerimaan bergantung pada sama ada kod tersebut memerlukan API yang stabil, suntikan kebergantungan, titik masuk yang boleh diperhatikan, atau penggunaan semula rentas modul. Alat operasi fail tunggal boleh menjadi lebih jelas dengan kurang formaliti; pustaka yang dikongsi, perkhidmatan yang berjalan lama, atau API yang didokumentasikan biasanya mendapat manfaat daripada kelas eksplisit.
Pertukaran kompromi dan sempadan
Kesederhanaan atau kebolehtemuan
Fail padat memastikan contoh pemula dekat dengan niat asalnya, tetapi nama tersirat dan peraturan import meningkatkan jumlah pengetahuan alatan yang diperlukan. Hadkan ciri ini kepada direktori berkandingan rendah dan dokumentasikan sempadan tersebut dalam piawaian pengekodan.
Main contoh atau main statik
Main contoh boleh menggunakan medan dan kaedah contoh secara langsung, yang sesuai untuk demonstrasi berkeadaan (stateful). Main statik mengikut laluan pelancaran Java tradisional dengan lebih rapat. Walau apa pun, pastikan tandatangan kemasukan adalah jelas supaya pelancar tidak melaporkan berbilang calon.
Import automatik atau import eksplisit
Peraturan atas permintaan java.base mengalih keluar import daripada kod pengajaran, tetapi jenis daripada modul lain masih memerlukan import modul atau import biasa yang eksplisit. Kod pengeluaran yang dikongsi harus menyatakan kebergantungan dengan jelas daripada bergantung pada pembaca untuk mengingati peraturan tersirat.
Latih tubi kegagalan dan evolusi
Berbilang calon main
Tambahkan kedua-dua titik masuk tanpa hujah dan tatasusunan String, kemudian sahkan bahawa bentuk tatasusunan yang diutamakan. Ubah jenis pulangan atau keterlihatan dan sahkan ralat serta tingkah laku sandaran pelancar.
Bergantung pada nama kelas tersirat
Minta fail sumber kedua merujuk nama kelas yang dijana, sahkan bahawa kompilasi gagal, dan pindahkan logik yang dikongsi ke dalam kelas yang dinamakan secara eksplisit.
Rantaian alatan yang tidak konsisten
Kompilasikan fail yang sama dengan JDK yang lebih lama dan Java 25. CI harus gagal serta-merta pada ketidakpadanan peringkat bahasa dan bukannya menangguhkan kegagalan sintaks ke masa jalanan.
Kesilapan lazim dan susulan
Kesilapan 1: Menganggap fail tidak mempunyai kelas
Susulan: Di manakah kaedah dan medan peringkat teratas berada? Ia adalah ahli bagi kelas tersirat yang dijana pengkompil dan masih mengikut peraturan ahli serta kitaran hayat contoh.
Kesilapan 2: Menganggap setiap import adalah automatik
Susulan: Mengapakah IO.println mesti menamakan kelas tersebut? Kaedah statik IO tidak diimport secara tersirat; jenis peringkat teratas awam java.base diimport atas permintaan.
Kesilapan 3: Memperlakukan sintaks skrip sebagai API yang stabil
Susulan: Bolehkah modul lain bergantung pada kelas tersirat? Ia tidak boleh bergantung pada nama pelaksanaan; API yang boleh diguna semula harus berada dalam kelas yang dinamakan secara eksplisit.
Susulan lebih mendalam dan jawapan model
Mengapakah main contoh memerlukan pembina lalai?
Selepas memilih titik masuk contoh, pelancar membina kelas yang diisytiharkan secara tersirat dan kemudian memanggil kaedah tersebut. Fail padat tidak mempunyai protokol hujah pembina, jadi suntikan luaran memerlukan kelas eksplisit.
Bagaimanakah pelaksanaan sumber langsung berbeza daripada kompilasi terlebih dahulu?
Pelaksanaan langsung membenarkan pelancar java mengkompilasi secara sementara dan menjalankan sumber tersebut, yang sesuai untuk skrip pendek. Mengkompilasi dengan javac terlebih dahulu memberikan artifak yang stabil, pencirian cache, dan diagnostik kepada CI dan sistem keluaran.
Bilakah anda patut kembali kepada kelas eksplisit?
Gunakan kelas bernama yang eksplisit apabila anda memerlukan nama jenis yang stabil, API awam, javadoc, suntikan kebergantungan, berbilang laluan pembinaan, atau penggunaan semula rentas modul, walaupun bentuk fail tunggal mempunyai lebih banyak kod berulang.