Câu hỏi Trong Java, sự khác biệt giữa gói riêng tư, công khai, được bảo vệ và riêng tư


Trong Java, có các quy tắc rõ ràng về thời điểm sử dụng từng công cụ sửa đổi truy cập, cụ thể là mặc định (gói riêng tư), public, protected và private, trong khi làm class và interface và đối phó với thừa kế?


2500
2017-10-18 19:53


gốc


private ẩn từ các lớp khác trong gói. public cho thấy các lớp bên ngoài gói. protected là một phiên bản của public chỉ giới hạn ở các lớp con. - Museful
@Tennenrishin - Không; trái với C ++, trong Java protected làm cho phương thức này cũng có thể truy cập được từ toàn bộ gói. Sự ngu xuẩn này trong mô hình visiblity của Java phá vỡ mục tiêu của protected. - Nicolas Barbulesco
@Nicolas Có thể truy cập từ toàn bộ gói, có hoặc không có protected. Là một truy cập bổ nghĩa, tất cả protected làm là để lộ ra các lớp con bên ngoài gói. - Museful
@tennenrishin - ừm, đó là những gì Nicolas đã nói ... và bạn đang lặp lại nó ngay bây giờ. Những gì ban đầu bạn nói là protected- và tôi trích dẫn - 'là một phiên bản của công chúng bị giới hạn chỉ cho các lớp con' mà không đúng bởi sự nhập học của riêng bạn vì được bảo vệ cũng cho phép truy cập thông qua toàn bộ gói (ergo, nó không hạn chế truy cập vào các lớp con.) - luis.espinal
Tôi cũng đồng ý với Nicolas rằng chế độ truy cập được bảo vệ trong Java là ngu ngốc. Điều gì đã xảy ra là Java bị bẻ cong ngang (mạng) và các giới hạn hạn chế truy cập dọc. Phạm vi mặc định là một giới hạn ngang / mạng với mạng là gói. Công cộng là một giới hạn ngang khác nơi mạng tinh thể là toàn bộ thế giới. Riêng tư và (C ++) được bảo vệ là dọc. Sẽ tốt hơn nếu chúng tôi có quyền truy cập chéo, protected-package trong những trường hợp hiếm hoi mà chúng ta thực sự cần đến nó, để lại protected tương đương với phiên bản C ++ được bảo vệ. - luis.espinal


Các câu trả lời:


Hướng dẫn chính thức có thể là một số sử dụng cho bạn.

            │ Lớp │ Gói │ Phân lớp │ Phân lớp │ Thế giới
            │ │ │ (cùng pkg) │ (diff pkg) │
──────────────────────────────────── ──┼────────
công khai │ + │ + │ + │ + │ +
──────────────────────────────────── ──┼────────
được bảo vệ │ + │ + │ + │ + │
──────────────────────────────────── ──┼────────
không có công cụ sửa đổi │ + │ + │ + │ │
──────────────────────────────────── ──┼────────
tư nhân │ + │ │ │ │

+: có thể truy cập
trống: không thể truy cập

4660
2017-10-18 19:57



Nếu bạn đang cố gắng để truy cập một phương pháp được bảo vệ hoặc biến dụ trong cùng một lớp nhưng trên một đối tượng đó không phải là bạn như trong trường hợp của .equals (Klass var) nó sẽ làm việc? - Jordan Medlock
Các trường mặc định được hiển thị trong các lớp con nếu các lớp con ở cùng một gói mà lớp cha của chúng. - Maksim Dmitriev
Trong các phiên bản Java và JDK lên đến 1.0.1, bạn có thể sử dụng riêng tư và được bảo vệ với nhau để tạo ra một hình thức bảo vệ khác để hạn chế quyền truy cập vào các phương thức hoặc biến duy nhất cho các lớp con của một lớp nhất định. - Vitalii Fedorenko
Đó là rất nhiều phiếu bầu cho một câu trả lời không trả lời câu hỏi, đó là khi nào chúng ta nên sử dụng mỗi khả năng hiển thị (không phải là những gì các hiệu ứng được). - Bohemian♦
@Bohemian - Câu trả lời giả định bạn biết bạn nên sử dụng specifier truy cập ít nhất cho phép bất cứ khi nào có thể (hoặc giả sử bạn đọc câu trả lời đầy đủ bằng cách theo liên kết cũng đưa ra lời khuyên đó). - iheanyi


(Caveat: Tôi không phải là một lập trình viên Java, tôi là một lập trình viên Perl. Perl không có sự bảo vệ chính thức nào có lẽ là lý do tại sao tôi hiểu vấn đề này :))

Riêng tư

Như bạn nghĩ, chỉ có lớp học trong đó nó được tuyên bố có thể nhìn thấy nó.

Gói riêng tư

Chỉ có thể được nhìn thấy và sử dụng bởi gói trong đó nó được tuyên bố. Đây là mặc định trong Java (một số được xem là một sai lầm).

Được bảo vệ

Gói Private + có thể được nhìn thấy bởi các lớp con hoặc thành viên gói.

Công cộng

Mọi người đều có thể nhìn thấy nó.

Được phát hành

Hiển thị bên ngoài mã tôi kiểm soát. (Trong khi không phải cú pháp Java, điều quan trọng cho cuộc thảo luận này).

C ++ định nghĩa một cấp độ bổ sung được gọi là "bạn" và bạn càng ít biết về điều đó càng tốt.

Khi nào bạn nên sử dụng cái gì? Toàn bộ ý tưởng là đóng gói để ẩn thông tin. Càng nhiều càng tốt, bạn muốn ẩn chi tiết về cách một cái gì đó được thực hiện từ người dùng của bạn. Tại sao? Bởi vì sau đó bạn có thể thay đổi chúng sau này và không phá vỡ mã của bất kỳ ai. Điều này cho phép bạn tối ưu hóa, tái cấu trúc, thiết kế lại và sửa lỗi mà không phải lo lắng rằng ai đó đang sử dụng mã mà bạn vừa sửa chữa.

Vì vậy, quy tắc của ngón tay cái là làm cho mọi thứ chỉ hiển thị như họ phải làm. Bắt đầu với riêng tư và chỉ thêm khả năng hiển thị khi cần. Chỉ làm cho công chúng trở nên hoàn toàn cần thiết để người dùng biết, mọi chi tiết bạn đưa ra đều làm cho công chúng của bạn bị hạn chế khả năng thiết kế lại hệ thống.

Nếu bạn muốn người dùng có thể tùy chỉnh hành vi, thay vì làm cho nội bộ công khai để họ có thể ghi đè lên chúng, thường là một ý tưởng tốt hơn để đẩy những người đó vào một đối tượng và đặt giao diện đó ở chế độ công khai. Bằng cách đó, họ có thể chỉ cần cắm vào một vật thể mới. Ví dụ, nếu bạn đang viết một đầu đĩa CD và muốn tùy biến bit "đi tìm thông tin về đĩa CD này", thay vì làm cho các phương thức đó công khai, bạn sẽ đặt tất cả các chức năng đó vào đối tượng riêng của nó và làm cho đối tượng getter / setter của bạn trở thành công khai . Bằng cách này là keo kiệt về phơi bày ruột của bạn khuyến khích thành phần tốt và tách mối quan tâm

Cá nhân, tôi chỉ gắn bó với "riêng tư" và "công khai". Nhiều ngôn ngữ OO chỉ có điều đó. "Được bảo vệ" có thể hữu ích, nhưng nó thực sự là một trò gian lận. Một khi một giao diện được nhiều hơn tư nhân nó nằm ngoài tầm kiểm soát của bạn và bạn phải đi tìm trong mã của người khác để tìm cách sử dụng.

Đây là nơi mà ý tưởng của "xuất bản" đi vào. Thay đổi một giao diện (refactoring nó) đòi hỏi rằng bạn tìm thấy tất cả các mã đang sử dụng nó và thay đổi điều đó, quá. Nếu giao diện là riêng tư, cũng không có vấn đề gì. Nếu nó được bảo vệ bạn phải đi tìm tất cả các lớp con của bạn. Nếu công khai, bạn phải tìm tất cả mã sử dụng mã của bạn. Đôi khi điều này là có thể, ví dụ nếu bạn đang làm việc trên mã công ty đó là để sử dụng nội bộ duy nhất nó không quan trọng nếu một giao diện được công khai. Bạn có thể lấy tất cả mã ra khỏi kho lưu trữ của công ty. Nhưng nếu một giao diện được "xuất bản", nếu có mã sử dụng nó bên ngoài kiểm soát của bạn, sau đó bạn đang hosed. Bạn phải hỗ trợ giao diện đó hoặc mã phá vỡ rủi ro. Ngay cả các giao diện được bảo vệ cũng có thể được xem là đã xuất bản (đó là lý do tại sao tôi không bận tâm đến việc bảo vệ).

Nhiều ngôn ngữ tìm thấy bản chất phân cấp của công cộng / được bảo vệ / riêng tư để quá hạn chế và không phù hợp với thực tế. Để kết thúc đó là khái niệm về một lớp đặc điểm, nhưng đó là một chương trình khác.


358
2017-10-18 21:17



Bạn bè -> "Bạn càng ít biết về nó thì càng tốt" ---> Nó mang lại khả năng hiển thị chọn lọc, điều này vẫn vượt trội so với quyền riêng tư của gói. Trong C ++, nó có các ứng dụng của nó, bởi vì không phải tất cả các hàm đều có thể là các hàm thành viên và bạn bè tốt hơn so với public'ing. Tất nhiên có nguy cơ lạm dụng bởi tâm trí tà ác. - Sebastian Mach
Cũng cần lưu ý rằng "được bảo vệ" trong C ++ có ý nghĩa khác - một phương thức được bảo vệ có hiệu quả riêng tư, nhưng vẫn có thể được gọi từ một lớp kế thừa. (Trái ngược với Java, nơi nó có thể được gọi bởi bất kỳ lớp nào trong cùng một gói.) - Rhys van der Waerden
@RhysvanderWaerden C # giống với C ++ ở khía cạnh này. Tôi thấy khá kỳ quặc rằng Java không cho phép khai báo một thành viên có thể truy cập được vào lớp con nhưng không cho phép toàn bộ gói. Đó là loại lộn ngược với tôi - một gói là phạm vi rộng hơn so với một lớp trẻ em! - Konrad Morawski
Gói @HOonMorawski IMHO có phạm vi nhỏ hơn lớp con. Nếu bạn chưa khai báo lớp cuối cùng của mình, người dùng sẽ có thể phân lớp nó - vì vậy bảo vệ java là một phần của giao diện đã xuất bản của bạn. OTOH, các gói được phát triển hoàn toàn bởi một tổ chức duy nhất: ví dụ: com.mycompany.mypackage. Nếu mã của bạn khai báo chính nó trong gói của tôi, bạn ngầm khai báo chính mình một phần của tổ chức của tôi, vì vậy chúng ta nên giao tiếp. Do đó, gói xuất bản đến một đối tượng nhỏ hơn / dễ tiếp cận hơn (những người trong công ty của tôi) hơn là phân lớp (những người mở rộng đối tượng của tôi) và do đó được tính là khả năng hiển thị thấp hơn. - Eponymous
friendlà tốt cho việc xác định các mối quan hệ đặc biệt giữa các lớp. Nó cho phép đóng gói cao cấp trong nhiều trường hợp khi được sử dụng đúng cách. Ví dụ, nó có thể được sử dụng bởi một lớp nhà máy đặc quyền để chèn các phụ thuộc nội bộ vào một kiểu được xây dựng. Nó có một tên xấu bởi vì những người không quan tâm đến việc duy trì chính xác một mô hình đối tượng được thiết kế tốt có thể lạm dụng nó để giảm khối lượng công việc của họ. - Dennis


Đây là một phiên bản tốt hơn của bảng. (Bằng chứng trong tương lai với một cột cho các mô-đun.)

Java Access Modifiers

Giải thích

  • A riêng tư thành viên là chỉ có có thể truy cập trong cùng một lớp với nó được khai báo.

  • Một thành viên với không có công cụ sửa đổi truy cập chỉ có thể truy cập trong các lớp học trong cùng một gói.

  • A được bảo vệ thành viên có thể truy cập trong tất cả các lớp trong cùng một gói  trong các lớp con trong các gói khác.

  • A công cộng thành viên có thể truy cập vào tất cả các lớp (trừ khi nó nằm trong một mô-đun không xuất gói được khai báo).


Công cụ sửa đổi nào để chọn?

Công cụ sửa đổi truy cập là công cụ giúp bạn ngăn chặn việc đóng gói vô tình(*). Hãy tự hỏi mình xem bạn có dự định thành viên là nội dung nào đó bên trong lớp, gói, phân cấp lớp hay không nội bộ hay không và chọn cấp truy cập cho phù hợp.

Ví dụ:

  • Một trường long internalCounter có thể là riêng tư vì nó có thể thay đổi và chi tiết triển khai.
  • Một lớp chỉ nên được khởi tạo trong một lớp nhà máy (trong cùng một gói) nên có một trình xây dựng bị giới hạn gói, vì không thể gọi nó trực tiếp từ bên ngoài gói.
  • Nội bộ void beforeRender() phương thức được gọi ngay trước khi kết xuất và được sử dụng như một móc trong các lớp con phải được bảo vệ.
  • A void saveGame(File dst) phương thức được gọi từ mã GUI phải được công khai.

(*) Đóng gói chính xác là gì?


245
2017-11-10 10:27





                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |   ✘   
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |       ✘       |   ✘   
————————————————+———————————————+———————————+———————————————+———————
private         |              |     ✘     |       ✘       |   ✘    

165
2018-01-09 21:42



Nó là giá trị đặt trong từ - "Sửa đổi bảo vệ làm cho đối tượng có sẵn trên các gói khác, trong khi mặc định / không có sửa đổi hạn chế quyền truy cập vào cùng một gói" - vanguard69
@ vanguard69, protected công cụ sửa đổi làm cho đánh dấu Điều (lớp, phương thức hoặc trường) có sẵn cho một số lớp khác trong một số gói khác chỉ iff cho biết lớp khác là lớp con của lớp mà ở đó protected- được đánh dấu Điều được khai báo. - Abdull
"nonsubbed"? "phân lớp này trong gói khác"? Huh. Tôi nghĩ tôi biết Java. - sehe
@AlexanderFarber bạn đã tối ưu hóa cho một cấu hình trình duyệt cụ thể chưa? Đây là chrome của tôi bây giờ và đây là Firefox - sehe
Hmm, hãy hoàn nguyên thay đổi của tôi - Alexander Farber


Quy tắc dễ dàng. Bắt đầu với tuyên bố mọi thứ riêng tư. Và sau đó tiến tới công chúng khi nhu cầu phát sinh và thiết kế đảm bảo nó.

Khi phơi bày các thành viên tự hỏi mình nếu bạn đang trưng bày lựa chọn đại diện hoặc lựa chọn trừu tượng. Đầu tiên là một cái gì đó bạn muốn tránh vì nó sẽ giới thiệu quá nhiều phụ thuộc vào sự biểu diễn thực tế hơn là trên hành vi quan sát của nó.

Theo nguyên tắc chung, tôi cố gắng tránh việc thực hiện phương thức ghi đè bằng cách phân lớp; nó quá dễ dàng để vít lên logic. Khai báo các phương thức được bảo vệ trừu tượng nếu bạn định để nó bị ghi đè.

Ngoài ra, sử dụng chú thích @Override khi ghi đè để giữ cho mọi thứ không bị phá vỡ khi bạn cấu trúc lại.


131
2017-10-18 20:00



@RuchirBaronia, "thế giới" = tất cả các mã trong ứng dụng, bất kể nó ở đâu. - Andrejs


Nó thực sự phức tạp hơn một chút so với một màn hình lưới đơn giản. Lưới điện cho bạn biết liệu quyền truy cập có được phép hay không, nhưng chính xác điều gì tạo thành quyền truy cập? Ngoài ra, các cấp truy cập tương tác với các lớp lồng nhau và thừa kế theo các cách phức tạp.

Quyền truy cập "mặc định" (được chỉ định bởi sự vắng mặt của từ khóa) cũng được gọi là gói riêng. Ngoại lệ: trong một giao diện, không có công cụ sửa đổi nào có nghĩa là truy cập công cộng; các công cụ sửa đổi khác ngoài công chúng bị cấm. Enum hằng số luôn được công khai.

Tóm lược

Quyền truy cập vào thành viên có thông số truy cập này có được phép không?

  • Thành Viên bây giờ là private: Chỉ khi thành viên được định nghĩa trong cùng một lớp với mã gọi.
  • Thành viên là gói riêng tư: Chỉ khi mã gọi nằm trong gói kèm theo ngay lập tức của thành viên.
  • Thành Viên bây giờ là protected: Cùng một gói, hoặc nếu thành viên được định nghĩa trong một siêu lớp của lớp có chứa mã gọi.
  • Thành Viên bây giờ là public: Vâng.

Các thông số truy cập nào áp dụng cho

Các biến cục bộ và các tham số chính thức không thể lấy các bộ định danh truy cập. Vì chúng vốn không thể tiếp cận với bên ngoài theo các quy tắc phạm vi, chúng có hiệu quả riêng tư.

Đối với các lớp ở phạm vi trên cùng, chỉ public và gói riêng tư được cho phép. Lựa chọn thiết kế này có lẽ là vì protected và private sẽ dư thừa ở cấp gói (không có gói thừa kế).

Tất cả các specifier truy cập đều có thể thực hiện trên các thành viên của lớp (các hàm tạo, các phương thức và các hàm thành viên tĩnh, các lớp lồng nhau).

Liên quan: Khả năng truy cập lớp Java

Gọi món

Các thông số truy cập có thể được sắp xếp nghiêm ngặt

công khai> được bảo vệ> gói riêng tư> riêng tư

điều đó có nghĩa là public cung cấp quyền truy cập nhiều nhất, private ít nhất. Bất kỳ tham chiếu nào có thể trên một thành viên tư nhân cũng có giá trị đối với thành viên riêng tư của gói; bất kỳ tham chiếu nào đến thành viên riêng tư của gói đều hợp lệ trên thành viên được bảo vệ, v.v. (Cấp quyền truy cập cho các thành viên được bảo vệ cho các lớp khác trong cùng một gói được coi là một sai lầm.)

Ghi chú

  • Các phương thức của lớp  được phép truy cập các thành viên riêng của các đối tượng khác trong cùng một lớp. Chính xác hơn, một phương thức của lớp C có thể truy cập các thành viên riêng của C trên các đối tượng của bất kỳ lớp con nào của C. Java không hỗ trợ giới hạn truy cập theo từng cá thể, chỉ bởi lớp. (So ​​sánh với Scala, nó hỗ trợ nó bằng cách sử dụng private[this].)
  • Bạn cần truy cập vào một hàm tạo để xây dựng một đối tượng. Vì vậy, nếu tất cả các nhà xây dựng là riêng tư, lớp chỉ có thể được xây dựng bằng mã sống trong lớp (thường là các phương thức nhà máy tĩnh hoặc các biến khởi tạo biến tĩnh). Tương tự đối với các nhà xây dựng gói riêng hoặc được bảo vệ.
    • Chỉ có các hàm tạo riêng cũng có nghĩa là lớp không thể được phân lớp bên ngoài, vì Java yêu cầu các hàm tạo của lớp con để ngầm gọi hoặc gọi một hàm tạo siêu lớp. (Tuy nhiên, nó có thể chứa một lớp lồng nhau phân lớp nó.)

Lớp bên trong

Bạn cũng phải cân nhắc lồng nhau phạm vi, chẳng hạn như các lớp bên trong. Một ví dụ về sự phức tạp là các lớp bên trong có các thành viên, mà bản thân chúng có thể lấy các công cụ sửa đổi truy cập. Vì vậy, bạn có thể có một lớp học riêng bên trong với một thành viên công cộng; thành viên có thể được truy cập không? (Xem bên dưới.) Quy tắc chung là xem xét phạm vi và suy nghĩ đệ quy để xem liệu bạn có thể truy cập từng cấp độ hay không.

Tuy nhiên, điều này khá phức tạp và đầy đủ chi tiết, tham khảo Đặc tả Ngôn ngữ Java. (Có, đã có lỗi trình biên dịch trong quá khứ.)

Để có được hương vị của các tương tác này, hãy xem xét ví dụ này. Có thể "rò rỉ" các lớp bên trong riêng tư; đây thường là một cảnh báo:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

Đầu ra trình biên dịch:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

Một số câu hỏi liên quan:


94
2017-09-13 07:38





Như một quy luật của:

  • riêng tư: phạm vi lớp.
  • mặc định (hoặc là gói riêng): phạm vi gói.
  • được bảo vệ: gói phạm vi + trẻ em (như gói, nhưng chúng ta có thể phân lớp nó từ các gói khác nhau). Trình sửa đổi được bảo vệ luôn giữ mối quan hệ "cha-con".
  • công cộng: mọi nơi.

Do đó, nếu chúng tôi chia quyền truy cập thành ba quyền:

  • (Thẳng thắn (gọi từ một phương thức bên trong cùng một lớp).
  • (Tài liệu tham khảo (gọi một phương thức sử dụng tham chiếu đến lớp, hoặc thông qua cú pháp "dấu chấm").
  • (Di sản (thông qua phân lớp).

thì chúng ta có bảng đơn giản này:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+

63
2017-12-18 18:01





Trong rất ngắn

  • public: có thể truy cập từ mọi nơi.
  • protected: có thể truy cập bởi các lớp của cùng một gói và các lớp con nằm trong bất kỳ gói nào.
  • mặc định (không có công cụ sửa đổi nào được chỉ định): có thể truy cập bởi các lớp của cùng một gói.
  • private: chỉ có thể truy cập trong cùng một lớp.

43
2017-10-27 17:49





Trình sửa đổi truy cập bị hiểu lầm nhiều nhất trong Java là protected. Chúng tôi biết rằng nó giống với công cụ sửa đổi mặc định với một ngoại lệ trong đó các lớp con có thể thấy nó. Nhưng bằng cách nào? Dưới đây là một ví dụ hy vọng làm rõ sự nhầm lẫn:

  • Giả sử chúng ta có 2 lớp; Father và Son, mỗi gói riêng của nó:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
    
  • Hãy thêm một phương thức được bảo vệ foo() đến Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
    
  • Phương pháp foo() có thể được gọi trong 4 ngữ cảnh:

    1. Bên trong một lớp học nằm trong cùng một gói foo() được định nghĩa (fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
      
    2. Bên trong một phân lớp, trên phiên bản hiện tại qua this hoặc là super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
      
    3. Trên tham chiếu có loại là cùng một lớp:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
      
    4. Trên một tham chiếu có kiểu là lớp cha và nó là phía trong gói nơi foo() được định nghĩa (fatherpackage) [Điều này có thể được bao gồm trong ngữ cảnh không. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
      
  • Các tình huống sau không hợp lệ.

    1. Trên một tham chiếu có kiểu là lớp cha và nó là ở ngoài gói nơi foo() được định nghĩa (fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
      
    2. Một lớp con không nằm trong một gói của một lớp con (Một lớp con kế thừa các thành viên được bảo vệ từ cha mẹ của nó, và nó làm cho chúng trở thành riêng tư với các lớp con không):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }
      

32
2017-11-15 20:06



Object#clone() là một ví dụ về protected hội viên. - Eng.Fouad
Sự khác biệt giữa làm super.foo() và tình huống không hợp lệ đầu tiên f.foo()? - cst1992
@ cst1992 Thật khó hiểu nhưng xem Đặc tả Ngôn ngữ Java 6.6.2: "Một thành viên được bảo vệ hoặc hàm tạo của một đối tượng có thể được truy cập từ bên ngoài gói mà nó được khai báo chỉ bằng mã chịu trách nhiệm thực hiện đối tượng đó". Với super.foo () tham chiếu "super" là "trực tiếp chịu trách nhiệm thực hiện" nhưng tham chiếu "f" thì không. Tại sao? Bởi vì bạn có thể chắc chắn 100% rằng "siêu" thuộc loại Cha, nhưng không phải cho "f"; vào thời gian chạy nó có thể là một loại phụ khác của Cha. Xem docs.oracle.com/javase/specs/jls/se9/html/… - skomisa
Thật thú vị khi đọc câu trả lời từ người hiểu protected. Thật không may, tất cả các câu trả lời khác trên trang này xác định protected làm cho nó hơi sai một chút. - Dawood ibn Kareem


Riêng tư

  • Phương pháp, Biến và Constructors

Phương thức, Biến và Constructors được khai báo riêng tư chỉ có thể được truy cập trong chính lớp được khai báo.

  • Lớp và giao diện

Công cụ sửa đổi truy cập riêng tư là mức truy cập hạn chế nhất. Lớp và giao diện không thể là riêng tư.

chú thích

Các biến được khai báo riêng có thể được truy cập bên ngoài lớp nếu các phương thức getter công khai có mặt trong lớp. Các biến, phương thức và hàm tạo được khai báo được bảo vệ trong một siêu lớp có thể được truy cập chỉ bởi các lớp con trong gói khác hoặc bất kỳ lớp nào trong gói của lớp của các thành viên được bảo vệ.


Được bảo vệ

  • Lớp và giao diện

Không thể áp dụng công cụ sửa đổi truy cập được bảo vệ cho lớp và giao diện.

Các phương thức, các trường có thể được khai báo được bảo vệ, tuy nhiên các phương thức và các trường trong một giao diện không thể được khai báo bảo vệ.

chú thích

Truy cập được bảo vệ cho lớp con cơ hội sử dụng phương thức trợ giúp hoặc biến, trong khi ngăn chặn một lớp không liên quan cố gắng sử dụng nó.


Công cộng

Một lớp, phương thức, hàm tạo, giao diện vv được khai báo công khai có thể được truy cập từ bất kỳ lớp nào khác. 

Do đó các trường, phương thức, các khối được khai báo bên trong một lớp public có thể được truy cập từ bất kỳ lớp nào thuộc về Vũ trụ Java.

  • Các gói khác nhau

Tuy nhiên, nếu lớp công khai mà chúng tôi đang cố truy cập nằm trong một gói khác, thì lớp công khai vẫn cần được nhập.

Vì thừa kế lớp, tất cả các phương thức công khai và các biến của một lớp được thừa hưởng bởi các lớp con của nó.


Mặc định -Không có từ khóa:

Trình sửa đổi truy cập mặc định có nghĩa là chúng tôi không khai báo rõ ràng một công cụ sửa đổi truy cập cho một lớp, trường, phương thức, v.v.

  • Trong cùng một gói

Một biến hoặc phương thức được khai báo mà không có bất kỳ công cụ sửa đổi điều khiển truy cập nào có sẵn cho bất kỳ lớp nào khác trong cùng một gói. Các trường trong một giao diện ngầm hoàn toàn là public static và các phương thức trong một giao diện được mặc định là public.

chú thích

Chúng tôi không thể ghi đè lên các trường tĩnh. Nếu bạn cố gắng ghi đè lên nó không hiển thị bất kỳ lỗi nào nhưng nó không hoạt động những gì chúng ta ngoại trừ.

Câu trả lời liên quan

Tham chiếu liên kết

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm 


24
2018-01-22 13:08