Bagaimana cara mengakses kelas-java di paket-default?

98

Saya sekarang bekerja sama dengan orang lain dalam proyek grails. Saya harus menulis beberapa kelas Java. Tapi saya butuh akses ke objek yang bisa dicari yang dibuat dengan groovy. Tampaknya, objek ini harus ditempatkan di paket default.

Pertanyaan saya adalah: Apakah ada cara untuk mengakses objek ini dalam paket default dari kelas Java dalam paket bernama?

Mnementh
sumber

Jawaban:

129

Anda tidak dapat menggunakan kelas dalam paket default dari paket bernama.
( Secara teknis Anda bisa, seperti yang ditunjukkan dalam jawaban Sharique Abdullah melalui API refleksi, tetapi kelas dari namespace yang tidak disebutkan namanya tidak dalam cakupan dalam deklarasi impor )

Sebelum J2SE 1.4 Anda dapat mengimpor kelas dari paket default menggunakan sintaks seperti ini:

import Unfinished;

Itu tidak lagi diizinkan . Jadi untuk mengakses kelas paket default dari dalam kelas yang dikemas memerlukan pemindahan kelas paket default ke dalam paketnya sendiri.

Jika Anda memiliki akses ke sumber yang dihasilkan oleh groovy, beberapa pemrosesan pasca diperlukan untuk memindahkan file ke dalam paket khusus dan menambahkan perintah "paket" ini di awal.


Pembaruan 2014: bug 6975015 , untuk JDK7 dan JDK8, jelaskan larangan yang lebih ketat terhadap impor dari paket yang tidak disebutkan namanya.

The TypeNameharus nama kanonik jenis kelas, jenis antarmuka, jenis enum, atau jenis anotasi.
Tipe harus salah satu anggota dari paket bernama , atau anggota tipe yang terluar tipe melampirkan secara leksikal adalah anggota dari paket bernama , atau kesalahan waktu kompilasi terjadi .


Andreas menunjukkan dalam komentarnya :

"mengapa [paket default] ada di tempat pertama? kesalahan desain?"

Tidak, itu disengaja.
JLS 7.4.2. Paket Tanpa Nama menyatakan: "Paket tanpa nama disediakan oleh platform Java SE terutama untuk kenyamanan saat mengembangkan aplikasi kecil atau sementara atau saat baru memulai pengembangan".

VonC
sumber
7
Seperti yang telah saya jelaskan kepada orang lain sebelumnya, paket default adalah warga kelas dua di dunia Java. Jangan Lakukan Itu. :-)
Chris Jester-Young
1
Sepertinya saya harus belajar Groovy (pada proyek yang sangat terbatas waktu) atau kode dalam paket default. :-(
Mnementh
11
@ ChrisJester-Young jika demikian, mengapa itu ada di tempat pertama? kesalahan desain?
Pacerier
Mengapa tidak digunakan lagi?
Suzan Cioc
@SuzanCioc maksud Anda: "mengapa setelah J2SE1.4, apakah Anda tidak dapat lagi mengakses paket default?"
VonC
61

Nyatanya, Anda bisa.

Dengan menggunakan API refleksi, Anda sejauh ini dapat mengakses kelas apa pun. Setidaknya saya bisa :)

Class fooClass = Class.forName("FooBar");
Method fooMethod = fooClass.getMethod("fooMethod", String.class);

String fooReturned = (String)fooMethod.invoke(fooClass.newInstance(), "I did it");
Holger
sumber
Untuk Scala, kode berikut berfungsi:val bar = "hi"; val fooClass = Class.forName("FooClass"); val fooMethod = fooClass.getMethod("foo", classOf[Array[String]]); val fooReturned = fooMethod.invoke(fooClass.newInstance(), Array(bar));
Jus12
2
Jawaban bagus, +1. Karena pertanyaannya asyik, bagaimanapun, Anda dapat menggunakan pengetikan bebek (seperti merekam Saluran, saya kira) ...Class.forName("FooBar").newInstance().fooMethod("I did it")
Bill K
7

Gunakan jarjar untuk mengemas ulang file jar dengan aturan berikut:

rule * <target package name>.@1

Semua kelas dalam paket default file jar sumber akan dipindahkan ke paket target, sehingga dapat mengakses.

Sean
sumber
4
demo tentang cara menggunakan jarjar akan sangat bagus
BiGGZ
@BiGGZ: Lihat README.md file di jarjar github repo untuk melihat bagaimana menggunakan jarjar dengan semut, Gradle atau baris perintah.
Lucidiot
3

Anda dapat menggunakan paket di Groovy kode, dan semuanya akan berfungsi dengan baik.

Ini mungkin berarti reorganisasi kecil kode di bawah grails-appdan sedikit sakit pada awalnya, tetapi pada proyek grails besar, masuk akal untuk mengatur hal-hal dalam paket. Kami menggunakan konvensi penamaan paket standar Java com.foo.<app>.<package>.

Memiliki semua yang ada di paket default menjadi penghalang integrasi, seperti yang Anda temukan.

Pengontrol tampaknya adalah artefak Grails (atau artefak) yang menolak dimasukkan ke dalam paket Java. Mungkin saya belum menemukan Conventionjawabannya. ;-)

Ken Gentle
sumber
0

hanya untuk menyelesaikan idenya:

Dari dalam paket default Anda dapat mengakses objek yang berada dalam paket bernama.

Duracell De Monaco
sumber