Tại sao Java cho phép chúng ta biên dịch một lớp có tên khác với tên tệp?


170

Tôi có một tập tin Test.javavà mã sau đây.

public class Abcd
{
        //some code here

}

Bây giờ lớp không biên dịch, nhưng khi tôi gỡ bỏ công cụ publicsửa đổi, nó sẽ biên dịch tốt.

Lý do đằng sau Java cho phép chúng ta biên dịch một tên lớp khác với tên tệp khi nó không công khai.

Tôi biết đó là một câu hỏi dành cho người mới, nhưng tôi không thể tìm thấy một lời giải thích tốt.


28
Vì Java. (Bởi vì nó không công khai và không phải tuân theo quy ước đặt tên tương tự. Ngoài ra, bạn cần phải hỏi những người đã phát minh ra nó.)
Dave Newton

2
Tôi nghi ngờ có một "lời giải thích tốt". Đó là một yêu cầu đối với các lớp học công cộng, nhưng nó được coi là không cần thiết đối với các lớp học ngoài công lập.
Kayaman

2
Có vẻ như một câu hỏi tương tự: stackoverflow.com/questions/7633631/ từ
sanket

4
Tại sao rất nhiều câu hỏi cho câu hỏi này, trước hết là câu hỏi trùng lặp của nó: stackoverflow.com/questions/7633631/ mẹo
GM Ramesh

2
@ Ramesh: tiêu đề và nội dung của câu hỏi này tốt hơn .. (so với những câu hỏi tương tự khác)
Jayan

Câu trả lời:


325

Lý do là cho phép nhiều hơn một lớp cấp cao nhất cho mỗi .javatệp.

Nhiều lớp, ví dụ như các trình lắng nghe sự kiện, chỉ sử dụng cục bộ và các phiên bản Java sớm nhất không hỗ trợ các lớp lồng nhau. Nếu không có quy tắc "filename = tên lớp" này, mỗi lớp như vậy sẽ yêu cầu tệp riêng của mình, với kết quả không thể tránh khỏi là sự tăng sinh vô tận của các .javatệp nhỏ và sự phân tán của mã được ghép chặt chẽ.

Ngay khi Java giới thiệu các lớp lồng nhau, tầm quan trọng của quy tắc này suy yếu đáng kể. Ngày nay, bạn có thể xem qua hàng trăm tệp Java, không bao giờ sử dụng một tệp tận dụng lợi thế của nó.


60
+1, điều này thực sự cung cấp một lý do , đó là câu hỏi.
Dave Newton

4
+1 cho thông tin lịch sử đặc biệt - Tôi nghi ngờ rằng với sự ra đời của các lớp lồng nhau / ẩn danh, nếu quyết định tương tự được đưa ra ngay bây giờ (không quan tâm đến khả năng tương thích ngược) sẽ có ý nghĩa hơn nhiều khi chỉ cho phép một lớp cấp cao nhất trên mỗi tập tin.
Michael Berry

1
@ berry120 Khá có thể, vì phụ cấp này làm phức tạp việc tìm kiếm tệp khi biên dịch.
Marko Topolnik

3
@Val Từ chối rằng những người khác muốn sử dụng trình soạn thảo văn bản và các công cụ CLI để phát triển bởi vì IDE mà bạn thích tồn tại cũng ngớ ngẩn như nói rằng không có điểm nào trong việc tạo IDE vì bạn có thể phát triển mà không cần chúng. Cả hai cách tiếp cận được sử dụng bởi các nhà phát triển tốt để tạo mã chất lượng; và điều duy nhất nhỏ hơn tỷ lệ cược của tất cả các nhà phát triển giải quyết một trong số họ và hát kumbaya là tỷ lệ cược mà tất cả chúng ta sẽ đồng ý về ngôn ngữ lập trình tốt nhất duy nhất là gì.
Dan đang loay hoay bởi Firelight 25/11/13

5
Sự kết hợp giữa Emacs (hoặc Vim, chọn chất độc của bạn) và các tiện ích shell Unix có lẽ không phải là tất cả trong tầm tay của bạn như một IDE hiện đại, và chúng chắc chắn khó học hơn, nhưng chúng có hai ưu điểm vượt trội so với mọi IDE tôi từng thử: chúng không bao giờ bị sập, cho dù codebase có lớn đến đâu và chúng có thể theo kịp cách gõ của tôi.
zwol

80

Lý do là giống như cho các tấm cửa. Nếu một người nào đó chính thức cư trú trong văn phòng (công khai) tên của anh ấy / cô ấy phải có trên thẻ cửa. Như "Alex Jones" hay "Thám tử Colombo". Nếu ai đó chỉ đến thăm phòng, nói chuyện với một quan chức hoặc lau sàn, tên của họ không phải được đặt chính thức trên cửa. Thay vào đó, cửa có thể đọc "Tiện ích" hoặc "Phòng họp".

Tên chính thức hoặc MyClass.java Phòng họp hoặc Test.java


4
Chắc chắn là một sự tương tự thú vị; nó có thể tốt hơn nữa với một chút giải thích về cách nó liên quan trực tiếp. OP có thể gặp một số khó khăn khi thực hiện kết nối (mặc dù tôi hiểu điều đó một cách hoàn hảo)
Andrew Barber

4
@AndrewBarber Tôi không nghĩ rằng sự tương tự thực sự phù hợp vì nó không mô hình hóa một lớp công khai, chia sẻ tệp với một số lớp riêng tư gói. Nó giống như tấm cửa đọc "Heather Santee, Manager", nhưng căn phòng thực sự chứa Heather và hai thư ký của cô.
Marko Topolnik

@MarkoTopolnik Tôi không nên tham gia vào việc này; Tôi là lớp A- khủng khiếp ở các tương tự! ;)
Andrew Barber

@AndrewBarber Dù sao tôi cũng muốn viết nó; bạn chỉ cần đẩy :) Sự tương tự cũng không thể hiện mối quan tâm cấp thiết nhất: chỉ vì tính năng này, trình biên dịch phải phân tích tất cả các tệp để khám phá tất cả các lớp trong trường hợp nó chỉ có thể đọc danh sách thư mục và biết tên của tất cả các lớp cấp cao nhất.
Marko Topolnik

@AndrewBarber, sự tương tự hoàn toàn phù hợp với ý tưởng của thư mục, trong hành lang dài bạn có thể nhanh chóng tìm thấy một người chỉ bằng cách liếc vào các tấm cửa, bạn không cần phải vào từng phòng và hỏi.
exebook

29

Đặc tả Java nói rằng bạn chỉ có thể có tối đa một lớp công khai cho mỗi tệp. Trong trường hợp này, tên lớp phải khớp với tên tệp. Tất cả các lớp ngoài công lập được phép có bất kỳ tên nào, bất kể tên tệp.


20
Nhưng "lý do đằng sau Java cho phép" chúng ta là gì?
Marko Topolnik

@MarkoTopolnik Bởi vì điều đó không ngăn cản chúng tôi: D
Maroun

8
@MarounMaroun Nhưng lý do đằng sau không ngăn cản chúng ta là gì?
Marko Topolnik

@Marko Java cho phép có nhiều lớp được định nghĩa trong cùng một tệp (miễn là chỉ một trong số chúng là công khai). Vì tất cả các lớp trong cùng một gói phải có một tên khác, không có lựa chọn nào khác ngoài việc cho phép các lớp không công khai có tên khác với tên tệp.
isnot2bad

2
2 xu của tôi: có lẽ nó được thiết kế theo cách này để nội địa hóa nhanh hơn các lớp bên trong classpath. Với quy ước này, việc kiểm tra tên / đường dẫn tệp là đủ để khám phá lớp. Nếu không có quy ước này, trình nạp lớp classpath có thể cần phải mở và phân tích các tệp để tìm các lớp
Andrei Nicusan

13

Tôi nghĩ cho phép chúng là điều kiện tiên quyết cho các lớp lồng nhau. Các lớp ẩn danh đặc biệt giảm đáng kể số lượng tệp .java cần thiết. Nếu không có sự hỗ trợ này, bạn sẽ cần rất nhiều triển khai giao diện phương thức đơn trong các tệp riêng của chúng từ lớp chính mà chúng được sử dụng. (Tôi đặc biệt nghĩ đến người nghe hành động)

Có một lời giải thích tốt về tất cả các lớp lồng nhau trong hướng dẫn Java Các lớp lồng nhau trên trang web của Oracle, trong đó có các ví dụ về mỗi lớp. Nó cũng có một lý do chúng hữu ích, mà tôi sẽ trích dẫn:

Tại sao nên sử dụng các lớp lồng nhau?

Lý do thuyết phục cho việc sử dụng các lớp lồng nhau bao gồm:

  • Đó là một cách phân nhóm hợp lý các lớp chỉ được sử dụng ở một nơi : Nếu một lớp chỉ hữu ích cho một lớp khác, thì việc nhúng nó vào lớp đó và giữ hai lớp lại với nhau là hợp lý. Việc lồng các "lớp trợ giúp" như vậy làm cho gói của chúng được sắp xếp hợp lý hơn.

  • Nó làm tăng sự đóng gói : Hãy xem xét hai lớp cấp cao nhất là A và B, trong đó B cần quyền truy cập vào các thành viên của A nếu không sẽ được khai báo là riêng tư. Bằng cách ẩn lớp B trong lớp A, các thành viên của A có thể được khai báo là riêng tư và B có thể truy cập chúng. Ngoài ra, bản thân B có thể bị ẩn khỏi thế giới bên ngoài.

  • Nó có thể dẫn đến mã dễ đọc và dễ bảo trì hơn : Lồng các lớp nhỏ trong các lớp cấp cao nhất đặt mã gần hơn với nơi nó được sử dụng.

(nhấn mạnh của tôi)

Tôi không quen với thông số kỹ thuật Java trong những ngày đầu, nhưng một tìm kiếm nhanh cho thấy các lớp bên trong đã được thêm vào trong Java 1.1.


Người ta phải làm gì trong trường hợp một loại chỉ hữu ích trong một loại khác, nhưng các thể hiện của loại trước không được liên kết với các thể hiện của loại sau?
supercat

Các lớp lồng nhau là cách Java 1.2 để thực hiện lambdas hoặc 'Hàm hạng nhất khi mọi thứ là một đối tượng'. Điều này đang thay đổi trong 1.8 Cú pháp. Chúng cũng được sử dụng khi chúng ta muốn mô hình hóa các kiểu dữ liệu đại số trong hệ thống Kiểu của Java.
hawkeye

12

Tôi nhìn nó theo cách khác. Trạng thái tự nhiên sẽ là để lập trình viên chọn cả tên lớp và tên tệp một cách độc lập. Có lẽ để đơn giản hóa việc tìm các lớp công khai từ bên ngoài một gói trong quá trình biên dịch, có một hạn chế đặc biệt là một lớp công khai nằm trong một tệp có tên tương ứng.


4

Lưu ý rằng Java phân biệt chữ hoa chữ thường, nhưng hệ thống tệp không cần. Nếu tên cơ sở của tệp là "abcd", nhưng lớp là "Abcd", điều đó có phù hợp với quy tắc trên hệ thống tệp không phân biệt chữ hoa chữ thường không? Chắc chắn là không khi chuyển sang trường hợp nhạy cảm.

Hoặc giả sử bạn tình cờ có một lớp được gọi là ABCD và một lớp Abcd (chúng ta đừng nghĩ đó là một ý tưởng tồi: nó có thể xảy ra) và chương trình được chuyển sang một hệ thống tệp không nhạy cảm. Bây giờ bạn không chỉ phải đổi tên các tập tin, mà còn các lớp, rất tiếc!

Hoặc nếu không có tập tin thì sao? Giả sử bạn có một trình biên dịch Java có thể nhận đầu vào trên đầu vào tiêu chuẩn. Vì vậy, lớp học phải được đặt tên là "StandardInput"?

Nếu bạn khám phá một cách hợp lý ý nghĩa của việc yêu cầu tên tệp theo tên lớp, bạn sẽ thấy rằng đó là một ý tưởng tồi theo nhiều cách.


Tôi đồng ý với những gì bạn nói, nhưng tôi không biết rằng nó đặc biệt trả lời câu hỏi ngoại trừ có thể giảm bớt một số vấn đề do kiến ​​trúc đặt tên bằng cách cho phép các tên lớp không công khai khác với tên tập tin. BTW, đối với trường hợp nhạy cảm với, nếu tôi được bắt nguồn một ngôn ngữ, trong bất kỳ phạm vi đã được Foođã được công bố, số nhận dạng FOO, foo, fOo, vv sẽ được tất cả "không xác định" ngay cả khi họ tồn tại trong phạm vi bên ngoài. Thiết kế như vậy sẽ loại bỏ vấn đề phân biệt chữ hoa chữ thường cho tên tệp.
supercat

3

Ngoài ra, một điểm khác mà nhiều câu trả lời bị bỏ lỡ chỉ ra là nếu không publickhai báo, JVM sẽ không bao giờ biết phương thức chính nào của lớp cần được gọi. Tất cả các lớp được khai báo trong một tệp .java đều có thể có các phương thức chính, nhưng phương thức chính chỉ được chạy trên lớp được đánh dấu là công khai. HTH


0

Do một tệp java có thể chứa nhiều hơn một lớp, nên nó có thể có hai lớp trong một tệp java. Nhưng một tệp java phải chứa một lớp có cùng tên với tên tệp nếu nó chứa một lớp chung.


Không, quy tắc đó chỉ áp dụng cho các lớp học công cộng.
deadboy 27/11/13
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.