Sự khác biệt giữa công khai, được bảo vệ, gói riêng tư và riêng tư trong Java là gì?


3171

Trong Java, đang có quy định rõ ràng về mỗi khi sử dụng các bộ điều chỉnh quyền truy cập, cụ thể là mặc định (gói tin), public, protectedprivate, trong khi thực hiện classinterfacevà xử lý thừa kế?


161
privateẩn từ các lớp khác trong gói. publictiếp xúc với các lớp bên ngoài gói. protectedlà một phiên bản publicchỉ giới hạn cho các lớp con.
Hồi giáo

87
@Tennenrishin - Không; trái với C ++, trong Java protectedlàm cho phương thức cũng có thể truy cập được từ toàn bộ gói. Sự ngu ngốc này trong mô hình độ nhớt của Java phá vỡ mục tiêu protected.
Nicolas Barbulesco

35
@Nicolas Có thể truy cập từ toàn bộ gói, có hoặc không có protected. Là một công cụ sửa đổi truy cập , tất cả những gì protectedcần làm là hiển thị cho các lớp con bên ngoài gói.
Hồi giáo

15
@tennenrishin - tốt, đó là những gì Nicolas đã nói ... và bạn chỉ đang lặp lại nó bây giờ. Điều ban đầu bạn nói là protected- và tôi xin trích dẫn - 'là phiên bản công khai chỉ giới hạn ở các lớp con', điều này không đúng với sự thừa nhận của bạn vì được bảo vệ cũng cho phép truy cập trong toàn bộ gói (ergo, nó không hạn chế quyền truy cập vào các lớp con. )
luis.espinal

10
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 đã xảy ra là các vòng loại hạn chế truy cập theo chiều ngang (mạng tinh thể) và Java. Phạm vi mặc định là một hạn chế ngang / lưới với mạng là gói. Công cộng là một hạn chế theo chiều ngang khác, trong đó mạng tinh thể là cả thế giới. Riêng tư và (C ++) được bảo vệ theo chiều dọc. Sẽ tốt hơn nếu chúng ta có quyền truy cập chéo, protected-packageđối với những trường hợp hiếm hoi mà chúng ta thực sự cần nó, để lại protectedtương đương với phiên bản C ++ được bảo vệ.
luis.espinal

Câu trả lời:


5639

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

Giới thiệu
| Lớp Gói │ Lớp con Lớp con │ Thế giới |
| │ │ (cùng pkg) │ (khác pkg) |
| ─ ─ ─ ─ ─ ─ ─ Giới thiệu |
| công cộng │ + + │ + │ + + | 
| ─ ─ ─ ─ ─ ─ ─ Giới thiệu |
| được bảo vệ │ + │ + + + | 
| ─ ─ ─ ─ ─ ─ ─ Giới thiệu |
| không có sửa đổi│ + + + │ | 
| ─ ─ ─ ─ ─ ─ ─ Giới thiệu |
| riêng tư │ + │ │ │ │ |
| ___________ | _______ | _________ | __________ | __________ | ______ |
 +: truy cập trống: không thể truy cập

5
Bảng trên không chính xác, vì thậm chí privatecác thành viên có thể được nhìn thấy / sử dụng bởi bất kỳ phương thức lớp / tĩnh nào trong cùng một tệp nguồn.
Usagi Miyamoto

5
Thành viên được bảo vệ chỉ có thể được truy cập từ lớp con của cùng một gói chứ không phải lớp con từ gói khác. Cần có một sự điều chỉnh trong bảng trên
niks

2
Thế giới là trong dự án của bạn . Tôi nên giải thích thêm. Các thư viện nằm trong dự án của bạn và nếu bạn đang tạo một thư viện, họ cũng sẽ trưng ra các lớp và phương thức công khai này. Vì vậy, nói chỉ trong dự án của bạn là một chút. "Tất cả mọi thứ sử dụng nó" là một mô tả tốt hơn.
adprocas

3
Ví dụ: nếu tôi có MyClassvà tôi đang làm, AnotherClass extends MyClasstôi sẽ có quyền truy cập vào tất cả các phương thức và thuộc tính được bảo vệ và công khai từ bên trong AnotherClass. Nếu tôi làm MyClass myClass = new MyClass();AnotherClassmột nơi nào đó - giả sử nhà xây dựng - tôi sẽ chỉ có quyền truy cập vào các phương thức công khai nếu nó nằm trong một gói khác. Lưu ý rằng nếu tôi làm điều = new MyClass() { @Override protected void protectedMethod() { //some logic } };đó có vẻ như tôi có thể truy cập các phương thức được bảo vệ, nhưng loại này giống như mở rộng nó, nhưng thay vào đó là nội tuyến.
adprocas

3
Thật không may, câu trả lời này là một sự đơn giản hóa quá mức. Thực tế phức tạp hơn một chút, đặc biệt là khi bạn xem xét protected(đây thực sự là một công cụ sửa đổi truy cập khá khó hiểu - hầu hết mọi người nghĩ rằng họ biết điều gì protectedthực sự không có nghĩa). Ngoài ra, như Bohemian đã chỉ ra, nó không trả lời câu hỏi - nó không nói về thời điểm sử dụng mỗi công cụ sửa đổi truy cập. Theo tôi, câu trả lời này là không hoàn toàn xấu, đủ để downvote, nhưng gần gũi. Nhưng hơn 4000 upvote? Làm sao chuyện này lại xảy ra?
Dawood ibn Kareem

483

(Caveat: Tôi không phải là lập trình viên Java, tôi là 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 đề rất tốt :))

Riêng tư

Giống như bạn nghĩ, chỉ có lớp được khai báo mới có thể nhìn thấy nó.

Gói riêng

Nó chỉ có thể được nhìn thấy và sử dụng bởi gói mà nó được khai báo. Đây là mặc định trong Java (mà một số người coi là một lỗi).

Đượ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. (Mặc dù không phải là cú pháp Java, nhưng điều này rất quan trọng cho cuộc thảo luận này).

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

Khi nào bạn nên sử dụng những gì? Toàn bộ ý tưởng là đóng gói để che giấu thông tin. Càng nhiều càng tốt, bạn muốn ẩn chi tiết về cách thực hiện một cái gì đó 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 đại tu.

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ư chúng phải có. Bắt đầu với tư nhân và chỉ thêm tầm nhìn khi cần thiết. Chỉ công khai những gì thực sự cần thiết cho người dùng biết, mọi chi tiết bạn đưa ra công khai sẽ làm giảm khả năng thiết kế lại hệ thống của bạn.

Nếu bạn muốn người dùng có thể tùy chỉnh các hành vi, thay vì công khai nội bộ để họ có thể ghi đè lên chúng, thì thường nên đưa những can đảm đó vào một đối tượng và đặt giao diện đó thành công khai. Bằng cách đó, họ có thể chỉ cần cắm vào một đối tượng mới. Ví dụ: nếu bạn đang viết một trình phát CD và muốn bit "đi tìm thông tin về CD này" có thể tùy chỉnh, thay vì công khai các phương thức đó, bạn sẽ đặt tất cả chức năng đó vào đối tượng của chính nó và chỉ công khai đối tượng getter / setter của bạn . Theo cách này là keo kiệt về việc phơi bày ruột của bạn khuyến khích thành phần tốt và tách biệt các 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ể có ích, nhưng nó thực sự là một trò gian lận. Khi một giao diện không chỉ riêng tư, nó nằm ngoài tầm kiểm soát của bạn và bạn phải tìm kiếm mã của người khác để tìm cách sử dụng.

Đây là nơi mà ý tưởng "xuất bản" xuất hiện. Thay đổi giao diện (tái cấu trúc nó) yêu cầu bạn tìm tất cả các mã đang sử dụng nó và cũng thay đổi điều đó. Nếu giao diện là riêng tư, cũng không có vấn đề. 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 nó công khai, bạn phải đi tìm tất cả cá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 với mã công ty chỉ sử dụng nội bộ thì không thành vấn đề nếu giao diện được công khai. Bạn có thể lấy tất cả cá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ó ngoài tầm kiểm soát của bạn, thì bạn đã bị hos. Bạn phải hỗ trợ giao diện đó hoặc có nguy cơ phá mã. Ngay cả các giao diện được bảo vệ có thể được coi là xuất bản (đó là lý do tại sao tôi không '

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ư là quá giới hạn và không phù hợp với thực tế. Cuối cùng, có khái niệm về một lớp đặc điểm , nhưng đó là một chương trình khác.


26
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ị có chọn lọc, vẫn vượt trội so với quyền riêng tư của gói. Trong C ++, nó có công dụng của nó, bởi vì không phải tất cả các chức năng đều có thể là chức năng thành viên và bạn bè tốt hơn so với công chúng. Tất nhiên có một nguy cơ lạm dụng bởi tâm trí xấu xa.
Sebastian Mach

30
Cũng cần lưu ý rằng "được bảo vệ" trong C ++ có một ý nghĩa khác - một phương thức được bảo vệ là riêng tư hiệu quả, 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

9
@RhysvanderWaerden C # giống với C ++ ở khía cạnh này. Tôi thấy khá kỳ lạ khi 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 phải toàn bộ gói. Đó là một loại lộn ngược với tôi - một gói có phạm vi rộng hơn một lớp con!
Konrad Morawski

15
Gói IMHO @KonradMorawski 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 java được bảo vệ 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 ngầm định bởi một tổ chức duy nhất: ví dụ: com.mycompany.mypackage. Nếu mã của bạn tự khai báo trong gói của tôi, bạn hoàn toàn tuyên bố mình là một phần của tổ chức của tôi, vì vậy chúng ta nên liên lạc. Do đó, gói xuất bản tới đố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) so với lớp con (những người mở rộng đối tượng của tôi) và do đó được tính là tầm nhìn thấp hơn.
Eponymous

2
friendlà tốt để xác định mối quan hệ đặc biệt giữa các lớp. Nó cho phép đóng gói vượt trội 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 để đưa 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ô hình đối tượng được thiết kế tốt có thể lạm dụng nó để giảm bớt khối lượng công việc của họ.
Dennis

434

Đây là phiên bản tốt hơn của bảng, bao gồm một cột cho các mô-đun.

Công cụ sửa đổi truy cập Java

Giải thích

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

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

  • Một thành viên được bảo vệ ( k) có thể truy cập được 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.

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


Chọn công cụ sửa đổi nào?

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

Ví dụ:

  • Một lĩnh vực long internalCountercó lẽ nên 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 hàm tạo bị hạn chế gói, vì không thể gọi nó trực tiếp từ bên ngoài gói.
  • Một void beforeRender()phương thức nội bộ được gọi là đúng trước khi kết xuất và được sử dụng như một hook trong các lớp con nên được bảo vệ.
  • Một void saveGame(File dst)phương thức được gọi từ mã GUI nên được công khai.

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


11
Chỉ cần nói: có rất nhiều người có vấn đề với việc phân biệt màu đỏ / xanh lá cây. Các bảng sử dụng bảng màu đỏ / xanh lá cây (hoặc vàng / cam / ...) hiếm khi "tốt hơn" ở bất cứ thứ gì ;-)
GhostCat

1
@GhostCat, tôi không đồng ý. Tôi nghĩ rằng màu đỏ / xanh Canh lề bằng trực giác với "tác phẩm" / "không làm việc" đối với nhiều người, tức là nó tốt hơn so với nhiều lựa chọn thay thế.
aioobe

8
colourblindawareness.org/colour-blindness/... ... Đã có 8% số màu mù đàn ông có thể được chia khoảng vào 1% deuteranopes, 1% protanopes, 1% protanomalous và 5% deuteranomalous . Và vì tôi là một trong 50% trong số 5% đó, hãy yên tâm: màu đỏ / xanh hút.
GhostCat

6
@GhostCat Ok .. đó là một phần dân số lớn hơn tôi mong đợi. Tôi đã tải lên hình ảnh trong trình giả lập mù màu này và thử nghiệm tất cả các chế độ khác nhau. Ngay cả trong chế độ đơn sắc / achromatopsia, sự khác biệt màu sắc là hợp lý. Bạn có thể thấy sự khác biệt hoặc là giả lập tắt? (Tôi vẫn cho rằng màu đỏ / xanh lá cây rất trực quan khi nhìn thấy màu sắc.)
aioobe 14/11/18

3
Tôi có thể thấy sự khác biệt, nhưng tôi cũng có thể vượt qua một nửa các bài kiểm tra mù màu mà chúng tôi phải làm ở Đức để lấy bằng lái xe ;-) ... nhưng tôi nghĩ một trình giả lập như vậy là "đủ tốt".
GhostCat

206
____________________________________________________________________
                | 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         |              |          |              |       
____________________________________________________________________

1
Thật đáng để nói - "Công cụ sửa đổi được 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ó công cụ sửa đổi hạn chế quyền truy cập vào cùng một gói"
vanguard69

2
@ vanguard69, các protectedsửa đổi làm cho rõ rệt điều (lớp, phương pháp, hoặc lĩnh vực) có sẵn cho một số lớp khác trong một số gói khác chỉ khi và chỉ khi nói lớp khác là một lớp con của lớp nơi mà protected- đánh dấu điều được khai báo.
Abdull

"Không được"? "Lớp con này trong gói khác"? Huh. Tôi nghĩ rằng 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ể? Đây là chrome của tôi bây giờ và đây là Firefox
sehe

Hmm, hãy hoàn nguyên sự thay đổi của tôi sau đó
Alexander Farber

165

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

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

Như một quy tắc chung, tôi cố gắng tránh ghi đè các cài đặt phương thức bằng cách phân lớp; quá dễ để làm hỏng logic. Khai báo các phương thức được bảo vệ trừu tượng nếu bạn định cho nó bị ghi đè.

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


3
@RuchirBaronia, "world" = tất cả mã trong ứng dụng, bất kể nó ở đâu.
Andrejs

116

Nó thực sự phức tạp hơn một chút so với một chương trình lưới đơn giản. Lưới 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 thì đ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à kế thừa theo những cách phức tạp.

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

Tóm lược

Có quyền truy cập vào một thành viên với chỉ định truy cập này được cho phép?

  • Thành viên là private: Chỉ khi thành viên được xác định 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ã cuộc 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 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 là public: Có.

Những thông số truy cập á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 chỉ định truy cập. Vì chúng vốn không thể tiếp cận được 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 trong phạm vi hàng đầu, chỉ publiccho phép và gói riêng tư được cho phép. Sự lựa chọn thiết kế này có lẽ là vì protectedprivatesẽ dư thừa ở cấp độ gói (không có sự kế thừa của các gói).

Tất cả các chỉ định truy cập đều có thể trên các thành viên lớp (hàm tạo, phương thức và 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

Đặt hàng

Các chỉ định truy cập có thể được ra lệnh nghiêm ngặt

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

có nghĩa là publiccung cấp nhiều quyền truy cập nhất, privateít nhất. Mọi tham chiếu có thể có về một thành viên tư nhân cũng có giá trị đối với một thành viên riêng tư trọn gói; mọi tham chiếu đến một thành viên riêng tư trọn gói đều hợp lệ đối với một thành viên được bảo vệ, v.v. (Cung 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 một 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 cùng 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ợ hạn chế truy cập theo thể hiện, chỉ theo lớp. (So ​​sánh với Scala, hỗ trợ sử dụng nó private[this].)
  • Bạn cần truy cập vào một constructor để xây dựng một đối tượng. Do đó, nếu tất cả các hàm tạo là riêng tư, lớp chỉ có thể được xây dựng bằng mã sống trong lớp (điển hình là các phương thức nhà máy tĩnh hoặc bộ khởi tạo biến tĩnh). Tương tự cho các nhà xây dựng gói riêng tư 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 gọi ngầm định hoặc rõ ràng là hàm tạo của lớp bậc trên. (Tuy nhiên, nó có thể chứa một lớp lồng nhau phân lớp nó.)

Lớp học bên trong

Bạn cũng phải xem xét các phạm vi lồng nhau , 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, chính chúng có thể lấy các bộ sửa đổi truy cập. Vì vậy, bạn có thể có một lớp bên trong riêng với một thành viên công cộng; thành viên có thể được truy cập? (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à để biết chi tiết đầy đủ, hãy tham khảo Đặc tả ngôn ngữ Java . (Vâng, đã có lỗi trình biên dịch trong quá khứ.)

Để biết cách thức tương tác, hãy xem xét ví dụ này. Có thể "rò rỉ" các lớp bên trong tư nhân; đâ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();
    }
}

Trình biên dịch đầu ra:

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:


1
"Các sửa đổi khác ngoài công khai bị cấm" - kể từ Java 9, đây không còn là trường hợp nữa: các giao diện cũng có thể có các phương thức riêng tư.
MC Hoàng đế

96

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

  • private: phạm vi lớp học.
  • default(hoặc package-private): phạm vi gói.
  • protected: package scope + child(giống như gói, nhưng chúng ta có thể phân lớp nó từ các gói khác nhau). Công cụ sửa đổi được bảo vệ luôn giữ mối quan hệ "cha-con".
  • public: mọi nơi.

Kết quả là, nếu chúng ta chia quyền truy cập thành ba quyền:

  • (D) irect (gọi từ một phương thức trong cùng một lớp hoặc thông qua cú pháp "this").
  • (R) eference (gọi một phương thức bằng cách sử dụng một tham chiếu đến lớp hoặc thông qua cú pháp "dot").
  • (I) nherribution (thông qua phân lớp).

sau đó 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   |
+—————————————————+————————————+———————————+

54

Rất ngắn

  • public: có thể truy cập từ khắp 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ó sửa đổi đượ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.

48

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

  • Giả sử rằng chúng ta có 2 lớp; FatherSon, mỗi gói trong gói riêng của mình:

    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()vào Father.

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

    1. Bên trong một lớp được đặt 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. Trong một lớp con, trong trường hợp hiện tại thông qua thishoặc super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
    3. Trên một 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ó loại là lớp cha và nó nằm trong gói foo()được định nghĩa ( fatherpackage) [Điều này có thể được bao gồm trong ngữ cảnh số. 1]:

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

    1. Trên một tham chiếu có kiểu là lớp cha và nó nằm ngoài gó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 không phải bên 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 riêng tư với các lớp không phải là lớp con):

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

Object#clone()là một ví dụ về một protectedthành viên.
Tiếng Anh.

Sự khác biệt giữa làm super.foo()và tình huống không hợp lệ đầu tiên là f.foo()gì?
cst1992

1
@ cst1992 Thật khó hiểu nhưng hãy xem Đặc tả ngôn ngữ Java 6.6.2: "Thành viên hoặc nhà xây dựng được bảo vệ của một đối tượng có thể được truy cập từ bên ngoài gói trong đó nó chỉ được khai báo bằng mã chịu trách nhiệm triển khai đối tượng đó". Với super.foo () tham chiếu "super" là "chịu trách nhiệm trực tiếp cho việc 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 là "f"; trong 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/iêu
skomisa

1
Thật sảng khoái khi đọc câu trả lời từ mộ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 protectedsai một chút.
Dawood ibn Kareem

30

Riêng tư

  • Phương thức, biến và hàm tạo

Các phương thức, biến và hàm xây dựng được khai báo là private 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 là cấp độ truy cập hạn chế nhất. Lớp và giao diện không thể là riêng tư.

Ghi chú

Các biến được khai báo là private 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 lớp bậc trên chỉ có thể được truy cập 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

Công cụ sửa đổi truy cập được bảo vệ có thể được áp dụng 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 được bảo vệ.

Ghi chú

Quyền truy cập được bảo vệ cung cấp cho lớp con cơ hội sử dụng phương thức hoặc biến của trình trợ giúp, đồng thời ngăn không cho 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, khối được khai báo bên trong một lớp công khai có thể được truy cập từ bất kỳ lớp nào thuộc Vũ trụ Java.

  • Gói khác nhau

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

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


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

Công cụ 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ỳ sửa đổi kiểm soát 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 hoàn toàn là công khai tĩnh cuối cùng và các phương thức trong một giao diện theo mặc định là công khai.

Ghi chú

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

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

Liên kết tham khảo

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifier.htmlm


21

Sự khác biệt có thể được tìm thấy trong các liên kết đã được cung cấp nhưng cái nào sẽ được sử dụng thường thuộc về "Nguyên tắc tối thiểu của kiến ​​thức". Chỉ cho phép tầm nhìn ít nhất là cần thiết.


20

Riêng tư : Chỉ giới hạn truy cập vào lớp

Mặc định (không có sửa đổi) : Quyền truy cập hạn chế vào lớp và gói

Được bảo vệ : Quyền truy cập hạn chế vào lớp, gói và các lớp con (cả gói bên trong và bên ngoài)

Công khai : Có thể truy cập vào lớp, gói (tất cả) và các lớp con ... Tóm lại, ở mọi nơi.


17

Công cụ sửa đổi truy cập ở đó để hạn chế quyền truy cập ở nhiều cấp độ.

Công khai: Về cơ bản là đơn giản như bạn có thể truy cập từ bất kỳ lớp nào cho dù đó là trong cùng một gói hay không.

Để truy cập nếu bạn ở cùng một gói, bạn có thể truy cập trực tiếp, nhưng nếu bạn ở gói khác thì bạn có thể tạo một đối tượng của lớp.

Mặc định: Có thể truy cập trong cùng một gói từ bất kỳ loại gói nào.

Để truy cập, bạn có thể tạo một đối tượng của lớp. Nhưng bạn không thể truy cập biến này bên ngoài gói.

Được bảo vệ: bạn có thể truy cập các biến trong cùng một gói cũng như lớp con trong bất kỳ gói nào khác. vì vậy về cơ bản nó là mặc định + Hành vi được kế thừa .

Để truy cập trường được bảo vệ được xác định trong lớp cơ sở, bạn có thể tạo đối tượng của lớp con.

Riêng tư: nó có thể được truy cập trong cùng một lớp.

Trong các phương thức không tĩnh, bạn có thể truy cập trực tiếp vì tham chiếu này (cũng trong các hàm tạo) nhưng để truy cập trong các phương thức tĩnh, bạn cần tạo đối tượng của lớp.


16

Sửa đổi truy cập trong Java.

Công cụ sửa đổi truy cập Java được sử dụng để cung cấp kiểm soát truy cập trong Java.

1. Mặc định:

Chỉ có thể truy cập vào các lớp trong cùng một gói.

Ví dụ,

// Saved in file A.java
package pack;

class A{
  void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B{
  public static void main(String args[]){
   A obj = new A(); // Compile Time Error
   obj.msg(); // Compile Time Error
  }
}

Quyền truy cập này bị hạn chế nhiều hơn công khai và được bảo vệ, nhưng ít bị hạn chế hơn riêng tư.

2. Công

Có thể được truy cập từ bất cứ đâu. (Truy cập toàn cầu)

Ví dụ,

// Saved in file A.java

package pack;
public class A{
  public void msg(){System.out.println("Hello");}
}

// Saved in file B.java

package mypack;
import pack.*;

class B{
  public static void main(String args[]){
    A obj = new A();
    obj.msg();
  }
}

Đầu ra: Xin chào

3. Riêng tư

Chỉ có thể truy cập trong cùng một lớp.

Nếu bạn cố gắng truy cập các thành viên riêng trên một lớp trong một lớp khác sẽ gây ra lỗi biên dịch. Ví dụ,

class A{
  private int data = 40;
  private void msg(){System.out.println("Hello java");}
}

public class Simple{
  public static void main(String args[]){
    A obj = new A();
    System.out.println(obj.data); // Compile Time Error
    obj.msg(); // Compile Time Error
  }
}

4. Được bảo vệ

Chỉ có thể truy cập vào các lớp trong cùng một gói và các lớp con

Ví dụ,

// Saved in file A.java
package pack;
public class A{
  protected void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B extends A{
  public static void main(String args[]){
    B obj = new B();
    obj.msg();
  }
}

Đầu ra: Xin chào

Nhập mô tả hình ảnh ở đây


14
  • công khai - có thể truy cập từ bất cứ đâu trong ứng dụng.

  • mặc định - có thể truy cập từ gói.

  • được bảo vệ - có thể truy cập từ gói và các lớp con trong gói khác. cũng

  • riêng tư - chỉ có thể truy cập từ lớp của nó.


14

Hiển thị với gói. Mặc định. Không cần sửa đổi.

Chỉ hiển thị với lớp ( riêng tư ).

Hiển thị với thế giới ( công cộng ).

Hiển thị với gói và tất cả các lớp con ( được bảo vệ ).

Các biến và phương thức có thể được khai báo mà không cần bất kỳ sửa đổi nào được gọi. Ví dụ mặc định:

String name = "john";

public int age(){
    return age;
}

Công cụ sửa đổi truy cập riêng tư - riêng tư:

Các phương thức, biến và hàm tạo được khai báo là private chỉ có thể được truy cập trong chính lớp được khai báo. Công cụ sửa đổi truy cập riêng là cấp truy cập hạn chế nhất. Lớp và giao diện không thể là riêng tư.

Các biến được khai báo là private 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.

Sử dụng công cụ sửa đổi riêng là cách chính mà một đối tượng tự gói gọn và che giấu dữ liệu khỏi thế giới bên ngoài.

Ví dụ:

Public class Details{

    private String name;

    public void setName(String n){
        this.name = n;
    }

    public String getName(){
        return this.name;
    }
}

Công cụ sửa đổi truy cập công cộng - công khai:

Một lớp, phương thức, hàm tạo, giao diện, v.v. 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, khối được khai báo bên trong một lớp công khai có thể được truy cập từ bất kỳ lớp nào thuộc vũ trụ Java.

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

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

Thí dụ:

public void cal(){

}

Công cụ sửa đổi truy cập được bảo vệ - được bảo vệ:

Các biến, phương thức và hàm tạo được khai báo được bảo vệ trong lớp bậc trên chỉ có thể được truy cập 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ông cụ sửa đổi truy cập được bảo vệ có thể được áp dụng 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 được bảo vệ.

Quyền truy cập được bảo vệ cung cấp cho lớp con cơ hội sử dụng phương thức hoặc biến của trình trợ giúp, đồng thời ngăn không cho lớp không liên quan cố gắng sử dụng nó.

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}

12

Trang này viết tốt về công cụ sửa đổi truy cập được bảo vệ và mặc định

.... Được bảo vệ: Công cụ sửa đổi truy cập được bảo vệ là một mẹo nhỏ và bạn có thể nói là siêu bộ điều chỉnh truy cập mặc định. Các thành viên được bảo vệ giống như các thành viên mặc định khi có liên quan đến quyền truy cập trong cùng một gói. Sự khác biệt là, các thành viên được bảo vệ cũng có thể truy cập được vào các lớp con của lớp mà thành viên được khai báo nằm ngoài gói mà lớp cha có mặt.

Nhưng những thành viên được bảo vệ này có thể truy cập bên ngoài gói chỉ thông qua thừa kế. tức là bạn có thể truy cập một thành viên được bảo vệ của một lớp trong lớp con của nó có mặt trong một số gói khác trực tiếp như thể thành viên đó có mặt trong chính lớp con đó. Nhưng thành viên được bảo vệ đó sẽ không thể truy cập được trong lớp con bên ngoài gói bằng cách sử dụng tham chiếu của lớp cha. ....


Chỉ cần thêm điều này "Một khi đứa trẻ được truy cập vào thành viên được bảo vệ của lớp cha, nó sẽ trở thành riêng tư (hay đúng hơn là tôi sẽ nói một thành viên riêng đặc biệt có thể được thừa kế bởi các lớp con của lớp con) của lớp con."
Anand

9

Câu trả lời của David cung cấp ý nghĩa của từng công cụ sửa đổi truy cập. Về thời điểm sử dụng mỗi loại, tôi khuyên bạn nên công khai tất cả các lớp và phương thức của từng lớp có nghĩa là sử dụng bên ngoài (API của nó) và mọi thứ khác ở chế độ riêng tư.

Theo thời gian, bạn sẽ phát triển ý thức khi nào thực hiện một số lớp riêng tư và khi nào khai báo một số phương thức được bảo vệ để sử dụng trong các lớp con.


6

Lưu ý: Đây chỉ là một bổ sung cho câu trả lời được chấp nhận.

Điều này có liên quan đến Công cụ sửa đổi truy cập Java .

Từ các sửa đổi truy cập Java :

Công cụ sửa đổi truy cập Java chỉ định các lớp nào có thể truy cập vào một lớp nhất định và các trường, hàm tạo và phương thức của nó. Bộ sửa đổi truy cập có thể được chỉ định riêng cho một lớp, các hàm tạo, các trường và các phương thức của nó. Công cụ sửa đổi truy cập Java đôi khi cũng được gọi trong lời nói hàng ngày là công cụ xác định truy cập Java, nhưng tên chính xác là công cụ sửa đổi truy cập Java. Các lớp, trường, hàm tạo và phương thức có thể có một trong bốn bộ sửa đổi truy cập Java khác nhau:

  • Danh sách mục
  • riêng tư
  • mặc định (gói)
  • bảo vệ
  • công cộng

Từ việc kiểm soát truy cập đến các thành viên của một lớp học :

Bộ sửa đổi mức truy cập xác định xem các lớp khác có thể sử dụng một trường cụ thể hoặc gọi một phương thức cụ thể. Có hai cấp độ kiểm soát truy cập:

  • Ở cấp độ cao nhất công khai, hoặc gói riêng tư (không có sửa đổi rõ ràng).
  • Ở cấp độ thành viên, công khai, riêng tư, được bảo vệ hoặc gói riêng tư (không có sửa đổi rõ ràng).

Một lớp có thể được khai báo với công cụ sửa đổi, trong trường hợp đó lớp đó hiển thị cho tất cả các lớp ở mọi nơi. Nếu một lớp không có công cụ sửa đổi (mặc định, còn được gọi là gói riêng tư), nó chỉ hiển thị trong gói riêng của nó

Bảng sau đây cho thấy quyền truy cập vào các thành viên được cho phép bởi mỗi người sửa đổi.

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
 Modifier     Class  Package  Subclass  World 
╠═════════════╬═══════╬═════════╬══════════╬═══════╣
 public       Y      Y        Y         Y     
 protected    Y      Y        Y         N     
 no modifier  Y      Y        N         N     
 private      Y      N        N         N     
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

Cột dữ liệu đầu tiên cho biết liệu chính lớp đó có quyền truy cập vào thành viên được xác định bởi cấp truy cập hay không. Như bạn có thể thấy, một lớp luôn có quyền truy cập vào các thành viên của chính nó. Cột thứ hai cho biết liệu các lớp trong cùng gói với lớp (bất kể nguồn gốc của chúng) có quyền truy cập vào thành viên hay không. Cột thứ ba cho biết liệu các lớp con của lớp được khai báo bên ngoài gói này có quyền truy cập vào thành viên hay không. Cột thứ tư cho biết liệu tất cả các lớp có quyền truy cập vào thành viên.

Cấp độ truy cập ảnh hưởng đến bạn theo hai cách. Đầu tiên, khi bạn sử dụng các lớp đến từ một nguồn khác, chẳng hạn như các lớp trong nền tảng Java, các mức truy cập sẽ xác định thành viên nào trong các lớp đó mà các lớp của riêng bạn có thể sử dụng. Thứ hai, khi bạn viết một lớp, bạn cần quyết định mức truy cập nào cho mỗi biến thành viên và mọi phương thức trong lớp của bạn nên có.


1
chính xác những gì là bổ sung, và tại sao nó không phải là một chỉnh sửa cho bài viết hiện có?
sehe

phần bổ sung là Bộ điều chỉnh truy cập. Tại sao không phải là một chỉnh sửa? Để giữ câu trả lời được chấp nhận không thay đổi vì lợi ích lịch sử và đưa ra câu trả lời của tôi.
שש א

5

Công khai mặc định và riêng tư là sửa đổi truy cập.

Chúng có nghĩa là để đóng gói, hoặc ẩn và hiển thị nội dung của lớp.

  1. Lớp có thể là công khai hoặc mặc định
  2. Các thành viên của lớp có thể là công khai, được bảo vệ, mặc định hoặc riêng tư.

Không thể truy cập riêng tư bên ngoài lớp Mặc định chỉ có thể truy cập trong gói. Được bảo vệ trong gói cũng như bất kỳ lớp nào mở rộng nó. Công khai cho tất cả.

Thông thường, các biến thành viên được định nghĩa riêng tư, nhưng các phương thức thành viên là công khai.


Defaultkhông phải là một sửa đổi truy cập, và hai trong số những người khác là sai chính tả.
Hầu tước Lorne

5

Thông thường, tôi đã nhận ra rằng việc ghi nhớ các khái niệm cơ bản của bất kỳ ngôn ngữ nào đều có thể thực hiện được bằng cách tạo ra các phép loại suy trong thế giới thực. Đây là sự tương tự của tôi để hiểu các công cụ sửa đổi truy cập trong Java:

Giả sử bạn là sinh viên của một trường đại học và bạn có một người bạn sẽ đến thăm bạn vào cuối tuần. Giả sử tồn tại một bức tượng lớn của người sáng lập trường đại học ở giữa khuôn viên.

  • Khi bạn đưa anh ấy đến khuôn viên trường, điều đầu tiên mà bạn và bạn của bạn nhìn thấy là bức tượng này. Điều này có nghĩa là bất cứ ai đi bộ trong khuôn viên trường đều có thể nhìn vào bức tượng mà không cần sự cho phép của trường đại học. Điều này làm cho bức tượng là CÔNG .

  • Tiếp theo, bạn muốn đưa bạn của bạn đến ký túc xá của bạn, nhưng vì điều đó bạn cần phải đăng ký anh ta như một khách truy cập. Điều này có nghĩa là anh ta có được một lượt truy cập (giống như của bạn) để vào các tòa nhà khác nhau trong khuôn viên trường. Điều này sẽ làm cho thẻ truy cập của anh ấy như được BẢO VỆ .

  • Bạn của bạn muốn đăng nhập vào WiFi của trường nhưng không có bất kỳ thông tin xác thực nào để làm như vậy. Cách duy nhất anh ấy có thể lên mạng là nếu bạn chia sẻ thông tin đăng nhập của mình với anh ấy. (Hãy nhớ rằng, mọi sinh viên đi học đại học cũng sở hữu những thông tin đăng nhập này). Điều này sẽ làm cho thông tin đăng nhập của bạn là KHÔNG CÓ SỬA ĐỔI .

  • Cuối cùng, bạn của bạn muốn đọc báo cáo tiến độ của bạn cho học kỳ được đăng trên trang web. Tuy nhiên, mỗi sinh viên có đăng nhập cá nhân của riêng họ để truy cập vào phần này của trang web của trường. Điều này sẽ làm cho những thông tin này là RIÊNG TƯ .

Hi vọng điêu nay co ich!


4

Khi bạn đang nghĩ về các công cụ sửa đổi truy cập, chỉ cần nghĩ về nó theo cách này (áp dụng cho cả biếnphương thức ):

public-> có thể truy cập từ mọi nơi
private-> chỉ có thể truy cập trong cùng một lớp nơi khai báo

Bây giờ sự nhầm lẫn xuất hiện khi nó đến defaultprotected

default-> Không có từ khóa sửa đổi truy cập có mặt. Điều này có nghĩa là nó có sẵn trong gói của lớp. Không nơi nào bên ngoài gói đó có thể được truy cập.

protected-> Ít nghiêm ngặt hơn một chút so với defaultvà ngoài các lớp gói giống nhau, nó có thể được truy cập bởi các lớp con bên ngoài gói mà nó được khai báo.


4

Truy cập Java sửa đổi mà bạn có thể sử dụng

nhập mô tả hình ảnh ở đây

Công cụ sửa đổi truy cập có thể được áp dụng cho class, field[Giới thiệu] , method. Cố gắng truy cập, phân lớp hoặc ghi đè này.

  • Truy cập fieldhoặc methodthông qua a class.
  • Di sản. Công cụ classsửa đổi truy cập kế thừa (lớp con) có thể là bất kỳ. Công cụ methodsửa đổi truy cập kế thừa (ghi đè) phải giống hoặc mở rộng nó

Lớp cấp cao nhất (phạm vi cấp đầu tiên) có thể publicdefault. Nested class[Giới thiệu] có thể có bất kỳ ai trong số họ

package không áp dụng cho phân cấp gói

Sửa đổi truy cập Swift


2

Đó là tất cả về đóng gói (hoặc như Joe Phillips đã nêu, ít kiến ​​thức nhất ).

Bắt đầu với phần hạn chế nhất (riêng tư) và xem bạn có cần sửa đổi ít hạn chế hơn sau này không.

Tất cả chúng ta đều sử dụng các công cụ sửa đổi phương thức và thành viên như private, public, ... nhưng một điều mà quá ít nhà phát triển làm là sử dụng các gói để tổ chức mã một cách hợp lý.

Ví dụ: Bạn có thể đặt các phương thức bảo mật nhạy cảm trong gói 'bảo mật'. Sau đó đặt một lớp nào đó truy cập vào một số mã có liên quan an ninh trong gói này nhưng giữ lớp bảo mật khác gói tin . Do đó, các nhà phát triển khác sẽ chỉ có thể sử dụng lớp có sẵn công khai từ bên ngoài gói này (trừ khi họ thay đổi công cụ sửa đổi). Đây không phải là một tính năng bảo mật, nhưng sẽ hướng dẫn sử dụng.

Outside world -> Package (SecurityEntryClass ---> Package private classes)

Một điều nữa là các lớp phụ thuộc rất nhiều vào nhau có thể kết thúc trong cùng một gói và cuối cùng có thể được tái cấu trúc hoặc sáp nhập nếu sự phụ thuộc quá mạnh.

Nếu ngược lại, bạn đặt mọi thứ là công khai thì sẽ không rõ những gì nên hoặc không nên truy cập, điều này có thể dẫn đến việc viết rất nhiều javadoc (không thực thi bất cứ điều gì thông qua trình biên dịch ...).


2

private-reserved-public-perfect-analogy-for-the-biến-data-type

Sơ đồ khối sau giải thích cách các thành viên dữ liệu của lớp cơ sở được kế thừa khi chế độ truy cập lớp dẫn xuấtriêng tư .

nhập mô tả hình ảnh ở đây

Lưu ý: Khai báo thành viên dữ liệu với chỉ định truy cập riêng được gọi là ẩn dữ liệu.

Nguồn: Thông số truy cập - Riêng tư, công cộng và được bảo vệ


1
Câu hỏi là về Java, không phải C ++.
Benoit

1
@Benoit Nhưng những gì tôi đã đăng, những bức ảnh đặc biệt, không giống nhau cho cả hai: java và c ++? Quy tắc này cũng không áp dụng cho java? cảm ơn
leonidaa

2
Trong C ++ chỉ có 3 sửa đổi, trong khi có 4 trong java.
Benoit

1
sự tương tự là tốt, nhưng chỉ định truy cập mặc định bị thiếu,
mss

1
OP đã đặt câu hỏi "Sự khác biệt giữa công khai, được bảo vệ, gói riêng tư và riêng tư trong Java là gì?"
JL_SO

2

Theo quan điểm của tôi :)

riêng tư:

lớp -> một lớp cấp cao nhất không thể là riêng tư. các lớp bên trong có thể là riêng tư có thể truy cập từ cùng một lớp.

biến thể hiện -> chỉ có thể truy cập trong lớp. Không thể truy cập bên ngoài lớp học.

gói riêng

lớp -> một lớp cấp cao nhất có thể là gói riêng. Nó chỉ có thể được truy cập từ cùng một gói. Không phải từ gói phụ, không phải từ gói bên ngoài.

biến thể hiện -> có thể truy cập từ cùng một gói. Không phải từ gói phụ, không phải từ gói bên ngoài.

được bảo vệ:

lớp -> một lớp cấp cao nhất không thể được bảo vệ.

biến thể hiện -> Chỉ có thể truy cập trong cùng một gói hoặc gói con. Chỉ có thể được truy cập bên ngoài gói trong khi mở rộng lớp.

công cộng:

lớp -> có thể truy cập từ gói / gói phụ / gói khác

biến thể hiện -> có thể truy cập từ gói / gói phụ / gói khác

Dưới đây là câu trả lời chi tiết

https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md


1
  • công cộng

    Nếu một thành viên lớp được khai báo với công chúng thì nó có thể được truy cập từ bất cứ đâu

  • bảo vệ

    Nếu một thành viên lớp được khai báo với từ khóa được bảo vệ thì nó có thể được truy cập từ cùng các thành viên lớp, bên ngoài các thành viên lớp trong cùng một gói và các thành viên lớp được kế thừa. Nếu một thành viên lớp được bảo vệ thì nó KHÔNG thể được truy cập từ lớp gói bên ngoài trừ khi lớp đóng gói bên ngoài được kế thừa tức là mở rộng lớp siêu lớp gói khác. Nhưng một thành viên của lớp được bảo vệ luôn có sẵn cho cùng các lớp gói, nó không quan trọng thời tiết cùng một lớp gói được kế thừa hay KHÔNG

  • mặc định

    Trong Java mặc định KHÔNG phải là một từ khóa sửa đổi truy cập. Nếu một thành viên lớp được khai báo mà không có bất kỳ từ khóa sửa đổi truy cập nào thì trong trường hợp này, nó được coi là thành viên mặc định. Thành viên lớp mặc định luôn có sẵn cho cùng các thành viên lớp gói. Nhưng thành viên lớp gói bên ngoài KHÔNG thể truy cập các thành viên lớp mặc định ngay cả khi các lớp bên ngoài là các lớp con không giống như các thành viên được bảo vệ

  • riêng tư

    Nếu một thành viên lớp được khai báo với từ khóa được bảo vệ thì trong trường hợp này, nó chỉ có sẵn cho các thành viên cùng lớp


-1

Trình xác định truy cập trong Java: Có 4 trình xác định truy cập trong java, cụ thể là riêng tư, gói riêng (mặc định), được bảo vệ và công khai theo thứ tự truy cập tăng dần.

Riêng tư : Khi bạn đang phát triển một số lớp và bạn muốn thành viên của lớp này không bị lộ ra ngoài lớp này thì bạn nên khai báo nó là riêng tư. các thành viên riêng tư chỉ có thể được truy cập trong lớp nơi chúng được định nghĩa tức là bao quanh lớp. Các thành viên riêng tư có thể được truy cập trên tài liệu tham khảo 'này' và cả các trường hợp khác của lớp kèm theo các thành viên này, nhưng chỉ trong định nghĩa của lớp này.

Gói-private (mặc định) : Trình xác định truy cập này sẽ cung cấp quyền truy cập được chỉ định bởi trình xác định truy cập riêng ngoài truy cập được mô tả bên dưới.

Khi bạn đang phát triển một số gói và do đó một số lớp (giả sử Class1) trong đó, bạn có thể sử dụng chỉ định truy cập mặc định (không cần đề cập rõ ràng), để hiển thị thành viên trong lớp, cho các lớp khác trong gói (cùng) của bạn. Trong các lớp khác này (trong cùng một gói), bạn có thể truy cập các thành viên mặc định này trên thể hiện của Class1. Ngoài ra, bạn có thể truy cập các thành viên mặc định này trong các lớp con của Class1, giả sử Class2 (trên tham chiếu này hoặc trên thể hiện của Class1 hoặc trên thể hiện của Class2).

Về cơ bản, trong cùng một gói, bạn có thể truy cập trực tiếp các thành viên mặc định của lớp hoặc trên tham chiếu 'this' trong các lớp con.

bảo vệ : Trình xác định truy cập này sẽ cung cấp quyền truy cập được chỉ định bởi trình xác định truy cập gói riêng ngoài truy cập được mô tả bên dưới.

Khi bạn đang phát triển một số gói và do đó một số lớp (nói Class1) trong đó, thì bạn nên sử dụng công cụ xác định truy cập được bảo vệ cho thành viên dữ liệu trong Class1 nếu bạn không muốn thành viên này được truy cập bên ngoài gói của bạn (nói là gói của người tiêu dùng gói của bạn tức là khách hàng đang sử dụng API của bạn) nói chung, nhưng bạn muốn tạo một ngoại lệ và chỉ cho phép truy cập vào thành viên này nếu khách hàng viết lớp nói Class2 mở rộng Class1. Vì vậy, nói chung, các thành viên được bảo vệ sẽ có thể truy cập được trên tham chiếu 'this' trong các lớp dẫn xuất, ví dụ Class2 và cả trên các thể hiện rõ ràng của Class2.

Xin lưu ý:

  1. Bạn sẽ không thể truy cập thành viên được bảo vệ kế thừa của Class1 trong Class2, nếu bạn cố gắng truy cập nó vào thể hiện rõ ràng của Class1, mặc dù nó được kế thừa trong nó.
  2. Khi bạn viết một Class3 khác trong cùng một gói / khác nhau mở rộng Class2, thành viên được bảo vệ từ Class1 sẽ có thể truy cập được trên tham chiếu này và cả trên ví dụ rõ ràng của Class3. Điều này sẽ đúng với bất kỳ hệ thống phân cấp nào được mở rộng, tức là thành viên được bảo vệ sẽ vẫn có thể truy cập được trên tài liệu tham khảo hoặc thể hiện của lớp mở rộng này. Lưu ý rằng trong Class3, nếu bạn tạo phiên bản của Class2 thì bạn sẽ không thể truy cập thành viên được bảo vệ từ Class1 mặc dù nó được kế thừa.

Vì vậy, điểm mấu chốt là, các thành viên được bảo vệ có thể được truy cập trong các gói khác, chỉ khi một số lớp từ gói khác này, mở rộng lớp kèm theo thành viên được bảo vệ này và thành viên được bảo vệ được truy cập vào 'trường hợp tham chiếu hoặc rõ ràng này của lớp mở rộng, theo định nghĩa của mở rộng lớp học.

công khai : Trình xác định truy cập này sẽ cung cấp quyền truy cập được chỉ định bởi trình xác định truy cập được bảo vệ ngoài quyền truy cập được mô tả bên dưới.

Khi bạn đang phát triển một số gói và do đó một số lớp (giả sử Class1) trong đó, thì bạn nên sử dụng công cụ xác định truy cập công khai cho thành viên dữ liệu trong Class1 nếu bạn muốn thành viên này có thể truy cập được trong các gói khác, ví dụ như Class1 được tạo trong một số lớp khác gói. Về cơ bản, công cụ xác định truy cập này nên được sử dụng khi bạn có ý định đưa thành viên dữ liệu của mình ra thế giới mà không cần bất kỳ điều kiện nào.

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.