2010-09-27 26 views
29

Có một tuyên bố trong cuốn sách tôi đang đọc cho trình độ SCJP, nó nói:Tại sao bạn lại muốn một tệp Java không có lớp công khai được khai báo trong đó?

tập tin không có lớp nào không có hạn chế đặt tên

đó đã làm cho tôi hỏi, tại sao bạn lại muốn làm điều này?

Nếu không có lớp học công khai, thì làm cách nào các lớp khác có thể nhập và sử dụng tệp? Mục đích duy nhất tôi có thể thấy là nếu tệp chạy độc lập, cũng có thể là lẻ, chẳng hạn như có toàn bộ ứng dụng trong một tệp

Trả lời

32

Điều này cũng hợp lệ cho các lớp package-private. Và bạn có thể sử dụng các lớp gói riêng trong cùng một gói. (Và trong trường hợp đó bạn không phải nhập nó, vì nó nằm trong cùng một gói.)

Ví dụ, lớp JapaneseImperialCalendar là gói riêng tư, vì nó chỉ được sử dụng từ Calendar.createCalendar(..) - nó không phải là một phần của API công khai. Bạn không thể trực tiếp khởi tạo lịch nhật ký, nhưng bạn vẫn có thể sử dụng nó bằng giao diện. Tương tự cho tất cả các bộ sưu tập không thể sửa đổi được thu được bằng các phương thức như Collections.unmodifiableList(..) - chúng là gói riêng tư.

Vì vậy, .java tệp của JapaneseImperialCalendar có thể tùy ý. Tuy nhiên, nó được khuyến khích không phải để phân kỳ từ thực tế được thành lập đặt tên ngay cả các tập tin gói riêng sau tên lớp.

+1

Khi tăng cường giữ nguyên thực hành đặt tên chỉ trong trường hợp, hãy lưu ý rằng [trạng thái JLS] (http://java.sun.com/docs/books/jls/third_edition/html/packages.html# 26783) rằng "hệ thống máy chủ có thể ... thực thi hạn chế rằng nó là một lỗi biên dịch thời gian nếu một loại không được tìm thấy trong một tập tin [với quy ước đặt tên]" ngay cả trong trường hợp loại chỉ "được gọi bằng mã trong các đơn vị biên dịch khác của gói trong đó loại được khai báo "(gói-riêng tư). –

1

Từ Java Classes, bạn có các lớp học công khai và các lớp học gói. Các lớp gói được coi là "riêng tư" để bạn chỉ có thể sử dụng chúng trong chính gói đó. Đây là mặc định, nghĩa là không có công khai được chỉ định.

Các lớp học công cộng, tất nhiên là các lớp học mà bạn có thể tạo ở mọi nơi.

2

Bạn có thể tạo tệp có tên package-info.java, chỉ chứa một tuyên bố package. Công cụ javadoc 1.5+ xử lý chú thích javadoc trên tuyên bố gói này chính xác như tệp package.html. Ngoài ra, bạn có thể thêm chú thích cấp gói chẳng hạn như @Generated vào tuyên bố này mà bạn không thể thực hiện trong package.html.

package-info không phải là số nhận dạng Java hợp lệ, không có nguy cơ tệp này từng xung đột với lớp Java hiện tại (nghĩa là khả năng tương thích ngược).

+3

Đó là (có thể) là một câu hỏi khác mà bạn đã trả lời ở đây .. – Tim

+1

Thực ra, đây là một ví dụ rất phù hợp vì sao một tệp như vậy sẽ không có giới hạn đặt tên. Tên tệp không phải là tên lớp hợp pháp, do đó, nó không thể là tệp có lớp trong đó (nhưng nó vẫn là * .java mà trình biên dịch sẽ xử lý theo các quy tắc được nêu trong JLS). – Barend

-2

Tôi không đồng ý với việc không hạn chế. Mỗi tệp java chỉ nên chứa một lớp cấp cao nhất và tên tệp phải giống với tên lớp, công khai hay không. Tôi không nghĩ rằng javac sẽ như thế này rất nhiều (hoặc bất kỳ con người)

A.java 
    class B 

B.java 
    class A 

http://java.sun.com/docs/books/jls/third_edition/html/packages.html#7.3

7.2 chủ Hỗ trợ cho gói

Mỗi máy chủ xác định các gói như thế nào, đơn vị biên soạn, và các gói con đang tạo ra và lưu trữ, và đó đơn vị biên soạn là quan sát (§7.3) trong một bộ sưu tập đặc biệt.

7.2.1 Lưu trữ Gói trong một File System

Như một ví dụ cực kỳ đơn giản,


http://download.oracle.com/javase/6/docs/technotes/tools/windows/javac.html

cả nguồn và lớp tập tin phải có tên gốc mà xác định lớp học. Ví dụ: một lớp được gọi là MyClass sẽ được viết trong tệp nguồn được gọi là MyClass.java và được biên dịch thành tệp lớp bytecode được gọi là MyClass.class.

+2

Nó được cho phép, giống như nó hay không. Đó là một câu hỏi khác nhau cho dù điều này có ý nghĩa trong trường hợp chung – Bozho

+0

@bozho nguồn gốc của quy ước tên tệp là gì? nó đã được một thời gian dài. – irreputable

+0

Có lẽ JLS. Tôi không biết làm thế nào nó đạt được điều đó :) – Bozho

-1

Mặc dù tôi rất chậm trả lời câu hỏi, nhưng điều này chắc chắn sẽ giúp ích rất nhiều. Nếu tôi không sai, câu hỏi cụ thể của bạn sẽ tóm tắt về điều này - Ý nghĩa của một lớp được khai báo là không có không có công cụ sửa đổi rõ ràng?

Hãy nhìn vào lớp học này hiện diện trong java.util package-

class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> 

Cũng xem trong cùng một package-

class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> 

Bạn thấy cả hai người trong số họ tuyên bố với không sửa đổi rõ ràng. Bạn có tự hỏi tại sao gói riêng tư hạn chế không? Dưới đây là những lý do từ cuốn sách tuyệt vời Effective Java 2nd Edition bởi Joshua Bloch # Item1

Lớp java.util.EnumSet (khoản 32), được giới thiệu trong phiên bản 1.5, có không constructors công cộng, chỉ các nhà máy tĩnh. Chúng trả về một trong hai cách triển khai, tùy thuộc vào kích thước của kiểu enum cơ bản: nếu nó có sáu mươi bốn hoặc ít hơn các phần tử, như là hầu hết các kiểu enum làm, các nhà máy tĩnh trả về cá thể RegularEnumSet , được hỗ trợ bởi Dài; nếu kiểu enum có sáu mươi lăm phần tử trở lên, các nhà máy trả về một cá thể JumboEnumSet, được hỗ trợ bởi một mảng dài .

Move nhanh chóng trên, ông tiếp tục adds-

Sự tồn tại của hai lớp thực hiện là vô hình để khách hàng. Nếu RegularEnumSet ngừng cung cấp các lợi thế về hiệu suất cho các loại enum nhỏ, nó có thể được loại bỏ khỏi bản phát hành trong tương lai mà không có các hiệu ứng bị ảnh hưởng.Tương tự như vậy, một bản phát hành trong tương lai có thể thêm một triển khai thực hiện thứ ba hoặc thứ tư của EnumSet nếu nó có lợi cho hiệu suất. Khách hàng không biết và cũng không quan tâm đến lớp đối tượng mà họ nhận được từ nhà máy; họ chỉ quan tâm rằng đó là một số phân lớp của EnumSet.

Các vấn đề liên quan