Hầu hết các câu trả lời ở đây đã tuyên bố rằng không có thứ gọi là gói con trong Java, nhưng điều đó không hoàn toàn chính xác. Thuật ngữ này đã có trong Đặc tả ngôn ngữ Java từ thời Java 6 và có thể quay trở lại (dường như không có phiên bản JLS có thể truy cập tự do cho các phiên bản Java trước đó). Ngôn ngữ xung quanh các gói con không thay đổi nhiều trong JLS kể từ Java 6.
Các thành viên của gói là các gói con của nó và tất cả các loại lớp cấp cao nhất và loại giao diện cấp cao nhất được khai báo trong tất cả các đơn vị biên dịch của gói.
Ví dụ: trong API nền tảng Java SE:
- Các gói phần mềm
javacó các gói con awt, applet, io, lang, net, và utilcác đơn vị, nhưng không có biên dịch.
- Gói
java.awtnày có một gói con được đặt tên image, cũng như một số đơn vị biên dịch có chứa các khai báo của các loại lớp và giao diện.
Khái niệm gói phụ có liên quan, vì nó thực thi các ràng buộc đặt tên giữa các gói và các lớp / giao diện:
Một gói có thể không chứa hai thành viên cùng tên hoặc kết quả lỗi thời gian biên dịch.
Dưới đây là một số ví dụ:
- Bởi vì gói
java.awtcó một gói con image, nó không thể (và không) chứa một khai báo của một lớp hoặc loại giao diện được đặt tên image.
- Nếu có một gói có tên
mousevà một loại thành viên Buttontrong gói đó (sau đó có thể được gọi là mouse.Button), thì không thể có bất kỳ gói nào có tên đủ điều kiện mouse.Buttonhoặc mouse.Button.Click.
- Nếu
com.nighthacks.java.jaglà tên đủ điều kiện của một loại, thì không thể có bất kỳ gói nào có tên đủ điều kiện là com.nighthacks.java.jaghoặc com.nighthacks.java.jag.scrabble.
Tuy nhiên, hạn chế đặt tên này là ý nghĩa duy nhất đủ khả năng để đóng gói theo ngôn ngữ:
Cấu trúc đặt tên phân cấp cho các gói nhằm thuận tiện cho việc tổ chức các gói liên quan theo cách thông thường, nhưng bản thân nó không có ý nghĩa gì ngoài việc cấm gói có gói con có cùng tên đơn giản như loại cấp cao nhất được khai báo trong gói đó .
Ví dụ, không có mối quan hệ truy cập đặc biệt giữa một gói có tên olivervà một gói khác có tên oliver.twist, hoặc giữa các gói có tên evelyn.woodvà evelyn.waugh. Nghĩa là, mã trong gói có tên oliver.twistkhông có quyền truy cập tốt hơn vào các loại được khai báo trong gói oliverso với mã trong bất kỳ gói nào khác.
Với bối cảnh này, chúng ta có thể tự trả lời câu hỏi. Vì rõ ràng không có mối quan hệ truy cập đặc biệt giữa một gói và gói phụ của nó, hoặc giữa hai gói phụ khác nhau của gói cha, nên không có cách nào trong ngôn ngữ để hiển thị một phương thức cho hai gói khác nhau theo cách được yêu cầu. Đây là một quyết định thiết kế tài liệu, cố ý.
Phương thức có thể được công khai và tất cả các gói (bao gồm odp.projvà odp.proj.test) sẽ có thể truy cập các phương thức đã cho hoặc phương thức có thể được đặt ở chế độ riêng tư (khả năng hiển thị mặc định) và tất cả các mã cần truy cập trực tiếp vào nó phải được đặt gói (phụ) giống như phương thức.
Điều đó nói rằng, một thực tiễn rất chuẩn trong Java là đặt mã kiểm tra vào cùng gói với mã nguồn, nhưng ở một vị trí khác trên hệ thống tệp. Ví dụ, trong công cụ xây dựng Maven , quy ước sẽ là đặt các tệp nguồn và kiểm tra này vào src/main/java/odp/projvà
src/test/java/odp/proj, tương ứng. Khi công cụ xây dựng biên dịch cái này, cả hai bộ tệp kết thúc trong odp.projgói, nhưng chỉ các srctệp được bao gồm trong tạo phẩm sản xuất; các tệp kiểm tra chỉ được sử dụng tại thời điểm xây dựng để xác minh các tệp sản xuất. Với thiết lập này, mã kiểm tra có thể tự do truy cập bất kỳ gói riêng tư hoặc mã được bảo vệ nào của mã mà nó đang kiểm tra, vì chúng sẽ nằm trong cùng một gói.
Trong trường hợp bạn muốn chia sẻ mã trên các gói con hoặc gói anh chị em không phải là trường hợp thử nghiệm / sản xuất, một giải pháp tôi đã thấy một số thư viện sử dụng là đặt mã chia sẻ đó thành công khai, nhưng tài liệu đó là dành cho thư viện nội bộ chỉ sử dụng.