จะเข้าถึง java-class ใน default-package ได้อย่างไร?


98

ตอนนี้ฉันกำลังทำงานร่วมกับคนอื่น ๆ ในโครงการเกรลส์ ฉันต้องเขียน Java-class บ้าง แต่ฉันต้องการเข้าถึงวัตถุที่สามารถค้นหาได้ที่สร้างขึ้นด้วยความน่ารัก ดูเหมือนว่าวัตถุนี้จะต้องถูกวางไว้ใน default-package

คำถามของฉันคือมีวิธีเข้าถึงอ็อบเจ็กต์นี้ใน default-package จาก Java-class ในชื่อ package หรือไม่?

คำตอบ:


129

คุณไม่สามารถใช้คลาสในแพ็คเกจเริ่มต้นจากแพ็คเกจที่มีชื่อ
(ในทางเทคนิคคุณสามารถทำได้ดังที่แสดงไว้ในคำตอบของ Sharique Abdullah ผ่านการสะท้อน API แต่คลาสจากเนมสเปซที่ไม่มีชื่อไม่อยู่ในขอบเขตในการประกาศการนำเข้า )

ก่อนหน้า J2SE 1.4 คุณสามารถอิมพอร์ตคลาสจากแพ็กเกจเริ่มต้นโดยใช้ไวยากรณ์ดังนี้:

import Unfinished;

ที่ไม่ได้รับอนุญาต ดังนั้นในการเข้าถึงคลาสแพ็กเกจเริ่มต้นจากภายในคลาสแพ็กเกจจำเป็นต้องย้ายคลาสแพ็กเกจเริ่มต้นไปยังแพ็กเกจของตนเอง

หากคุณสามารถเข้าถึงซอร์สที่สร้างโดย groovy ได้จำเป็นต้องมีการประมวลผลภายหลังเพื่อย้ายไฟล์ไปยังแพ็กเกจเฉพาะและเพิ่มคำสั่ง "แพ็กเกจ" นี้ที่จุดเริ่มต้น


อัปเดต 2014: ข้อผิดพลาด 6975015สำหรับ JDK7 และ JDK8 อธิบายถึงข้อห้ามที่เข้มงวดยิ่งขึ้นต่อการนำเข้าจากแพ็คเกจที่ไม่มีชื่อ

TypeNameจะต้องเป็นชื่อที่ยอมรับจากประเภทชั้นประเภทอินเตอร์เฟซชนิด enum หรือประเภทคำอธิบายประกอบ
ชนิดต้องเป็นสมาชิกของแพคเกจที่มีชื่อหรือสมาชิกของประเภทที่มีชั้นนอกสุดประเภท lexically ล้อมรอบเป็นสมาชิกของที่แพคเกจชื่อ , หรือรวบรวมข้อผิดพลาดเกิดขึ้นเวลา


Andreasชี้ให้เห็นในความคิดเห็น :

"ทำไมจึงมี [แพ็กเกจเริ่มต้น] ตั้งแต่แรกข้อผิดพลาดในการออกแบบ?"

ไม่มันจงใจ
JLS 7.4.2 แพคเกจที่ไม่มีชื่อกล่าวว่า: "แพ็กเกจที่ไม่มีชื่อให้บริการโดยแพลตฟอร์ม Java SE โดยเฉพาะเพื่อความสะดวกในการพัฒนาแอปพลิเคชันขนาดเล็กหรือชั่วคราวหรือเมื่อเพิ่งเริ่มการพัฒนา"


7
ดังที่ฉันได้อธิบายให้คนอื่นฟังก่อนหน้านี้แพ็คเกจเริ่มต้นคือพลเมืองชั้นสองในโลก Java อย่าทำอย่างนั้น :-)
Chris Jester-Young

1
ดูเหมือนว่าฉันต้องเรียนรู้ Groovy (ในโครงการที่ จำกัด เวลามาก) หรือรหัสในแพ็คเกจเริ่มต้น :-(
Mnementh

11
@ ChrisJester-Young ถ้างั้นทำไมถึงมีตั้งแต่แรก? ข้อผิดพลาดในการออกแบบ?
Pacerier

เหตุใดจึงเลิกใช้งาน
Suzan Cioc

@SuzanCioc คุณหมายถึง: "ทำไมหลังจาก J2SE1.4 คุณไม่สามารถเข้าถึงแพ็กเกจเริ่มต้นได้อีกต่อไป"
VonC

61

ในความเป็นจริงคุณสามารถ

เมื่อใช้ reflections API คุณสามารถเข้าถึงคลาสใดก็ได้ อย่างน้อยฉันก็สามารถ :)

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

String fooReturned = (String)fooMethod.invoke(fooClass.newInstance(), "I did it");

สำหรับ Scala รหัสต่อไปนี้ใช้งานได้: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
คำตอบที่ดี +1 อย่างไรก็ตามเนื่องจากคำถามนั้นหนักหน่วงคุณสามารถใช้การพิมพ์แบบเป็ด (เช่นการบันทึกเทปฉันเดา) ...Class.forName("FooBar").newInstance().fooMethod("I did it")
Bill K

7

ใช้jarjarเพื่อบรรจุไฟล์ jar ใหม่ด้วยกฎต่อไปนี้:

rule * <target package name>.@1

คลาสทั้งหมดในแพ็กเกจเริ่มต้นของไฟล์ jar ต้นทางจะย้ายไปยังแพ็กเกจเป้าหมายดังนั้นจึงสามารถเข้าถึงได้


4
การสาธิตวิธีใช้ jarjar จะดีมาก
BiGGZ

@BiGGZ: ดูไฟล์README.mdบน repo jarjar github เพื่อดูวิธีใช้ jarjar กับ ant, gradle หรือบรรทัดคำสั่ง
Lucidiot

3

คุณสามารถใช้แพ็คเกจในGroovyรหัสและสิ่งต่างๆจะทำงานได้ดี

อาจหมายถึงการจัดระเบียบโค้ดใหม่เล็กน้อยภายใต้grails-appและความเจ็บปวดเล็กน้อยในตอนแรก แต่สำหรับโครงการที่มีขนาดใหญ่การจัดระเบียบสิ่งต่างๆในแพ็คเกจก็เป็นเรื่องที่สมเหตุสมผล com.foo.<app>.<package>เราใช้แพคเกจการประชุมตั้งชื่อ Java มาตรฐาน

การมีทุกอย่างในแพ็คเกจเริ่มต้นจะกลายเป็นอุปสรรคต่อการผสานรวมอย่างที่คุณพบ

ตัวควบคุมดูเหมือนจะเป็นสิ่งประดิษฐ์ Grails (หรือสิ่งประดิษฐ์) ที่ต่อต้านการใส่ในแพ็คเกจ Java อาจเป็นไปได้ว่าฉันยังไม่ได้Conventionหาสิ่งนั้น ;-)


0

เพียงเพื่อให้ความคิดสมบูรณ์:

จากภายในแพ็คเกจเริ่มต้นคุณสามารถเข้าถึงวัตถุที่อยู่ในแพ็คเกจที่มีชื่อ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.