Bộ định nghĩa truy cập mặc định trong Java là gì?


108

Tôi vừa mới bắt đầu đọc một cuốn sách Java và tự hỏi; thông số truy cập nào là mặc định, nếu không có chỉ định nào?


Thuật ngữ chính xác là 'công cụ sửa đổi truy cập'. Từ 'specifier' không xuất hiện trong JLS.
Marquis of Lorne

Câu trả lời:


116

Khả năng hiển thị mặc định được gọi là “package-private” (mặc dù bạn không thể sử dụng nó một cách rõ ràng), có nghĩa là trường sẽ có thể truy cập được từ bên trong cùng một gói mà lớp thuộc về.

Như mdma đã chỉ ra, nó không đúng với các thành viên giao diện, mặc định là "công khai".

Xem các chỉ định truy cập của Java


25
không đúng - không đúng cho các thành viên giao diện. quyền truy cập mặc định sau đó là công khai
mdma 13/09/13

2
Nó thực sự được gọi là 'gói riêng tư'. Các trang web của bên thứ ba không phải là tham chiếu chuẩn. Bạn chỉ nên trích dẫn JLS.
Marquis of Lorne

81

Thông số kỹ thuật mặc định phụ thuộc vào ngữ cảnh.

Đối với các lớp và khai báo giao diện, mặc định là gói riêng tư. Điều này nằm giữa được bảo vệ và riêng tư, chỉ cho phép các lớp trong cùng một gói truy cập. (được bảo vệ giống như thế này, nhưng cũng cho phép truy cập vào các lớp con bên ngoài gói.)

class MyClass   // package private
{
   int field;    // package private field

   void calc() {  // package private method

   }
}

Đối với các thành viên giao diện (trường và phương thức), quyền truy cập mặc định là công khai. Nhưng lưu ý rằng bản thân khai báo giao diện được mặc định là gói riêng tư.

interface MyInterface  // package private
{
   int field1;         // static final public

   void method1();     // public abstract
}

Nếu sau đó chúng ta có khai báo

public interface MyInterface2 extends MyInterface
{

}

Các lớp sử dụng MyInterface2 sau đó có thể thấy field1 và method1 từ siêu giao diện, bởi vì chúng là công khai, mặc dù chúng không thể nhìn thấy phần khai báo của chính MyInterface.


1
"Gói riêng tư" (đôi khi được viết bằng nguồn là /* pp */) chỉ là một tên thuận tiện cho truy cập mặc định . Nó không phải là tên JLS.
Tom Hawtin - tackline

10
@Tom - đúng vậy, JLS sử dụng "quyền truy cập mặc định". Tôi có thể đã viết "mặc định là quyền truy cập mặc định". Nhưng điều đó dường như không quá hữu ích!
mdma

16

Nếu không có mã xác định quyền truy cập nào được cung cấp, thì đó là quyền truy cập mức gói (không có mã xác định rõ ràng cho điều này) cho các lớp và thành viên lớp. Các phương thức giao diện là công khai hoàn toàn.


9

Khả năng hiển thị mặc định (không có từ khóa) là gói có nghĩa là nó sẽ có sẵn cho mọi lớp nằm trong cùng một gói.

Lưu ý bên cạnh thú vị là được bảo vệ không giới hạn khả năng hiển thị đối với các lớp con mà còn đối với các lớp khác trong cùng một gói


8

Nó phụ thuộc vào sự vật là gì.

  • Các kiểu cấp cao nhất (nghĩa là các lớp, enums, giao diện và các kiểu chú thích không được khai báo bên trong một kiểu khác) theo mặc định là gói riêng tư . ( JLS §6.6.1 )

  • Trong các lớp, tất cả các thành viên (có nghĩa là các trường, phương thức và khai báo kiểu lồng nhau) và các hàm tạo là gói riêng theo mặc định. ( JLS §6.6.1 )

    • Khi một lớp không có phương thức khởi tạo được khai báo rõ ràng, trình biên dịch sẽ chèn một phương thức khởi tạo không đối số mặc định có cùng định nghĩa truy cập như lớp đó . ( JLS §8.8.9 ) Hàm tạo mặc định thường bị hiểu sai là luôn luôn là công khai, nhưng trong một số trường hợp hiếm hoi , hàm tạo này không tương đương.
  • Trong enums, các hàm tạo là private theo mặc định. Thật vậy, enum contructors phải là private, và việc chỉ định chúng là public hay protected là một lỗi. Hằng số enum luôn là công khai và không cho phép bất kỳ mã xác định quyền truy cập nào. Các thành viên khác của enums là gói-riêng theo mặc định. ( JLS §8.9 )

  • Trong giao diện và kiểu chú thích, tất cả các thành viên (một lần nữa, điều đó có nghĩa là các trường, phương thức và khai báo kiểu lồng nhau) là công khai theo mặc định. Thật vậy, các thành viên của các giao diện và các loại chú thích phải ở chế độ công khai, và việc chỉ định chúng là riêng tư hoặc được bảo vệ là một lỗi. ( JLS §9.3 đến 9.5 )

  • Các lớp cục bộ là các lớp được đặt tên được khai báo bên trong một phương thức, phương thức khởi tạo hoặc khối khởi tạo. Chúng nằm trong phạm vi {.. }khối mà chúng được khai báo và không cho phép bất kỳ trình xác định quyền truy cập nào. ( JLS §14.3 ) Sử dụng phản chiếu, bạn có thể khởi tạo các lớp cục bộ từ nơi khác và chúng là gói riêng tư , mặc dù tôi không chắc liệu chi tiết đó có trong JLS hay không.

  • Các lớp ẩn danh là các lớp tùy chỉnh được tạo ra newđể chỉ định một phần thân của lớp trực tiếp trong biểu thức. ( JLS §15.9.5 ) Cú pháp của chúng không cho phép bất kỳ trình xác định quyền truy cập nào. Bằng cách sử dụng phản chiếu, bạn có thể khởi tạo các lớp ẩn danh từ nơi khác và cả chúng và các hàm tạo được tạo của chúng đều là gói riêng tư , mặc dù tôi không chắc liệu chi tiết đó có trong JLS hay không.

  • Các khối khởi tạo phiên bản và tĩnh không có mã xác định truy cập ở cấp ngôn ngữ ( JLS §8.6 & 8.7 ), nhưng các khối khởi tạo tĩnh được triển khai dưới dạng một phương thức có tên <clinit>( JVMS §2.9 ), do đó, trong nội bộ phương thức phải có một số chỉ định truy cập. Tôi đã kiểm tra các lớp được biên dịch bởi javac và bởi trình biên dịch của Eclipse bằng trình soạn thảo hex và thấy rằng cả hai đều tạo ra phương thức dưới dạng gói-riêng . Tuy nhiên, bạn không thể gọi <clinit>()trong ngôn ngữ bởi vì các ký tự <>không hợp lệ trong tên phương thức và các phương thức phản chiếu được làm cứng để phủ nhận sự tồn tại của nó, do đó, chỉ định truy cập của nó thực sự là không có quyền truy cập . Phương thức chỉ có thể được gọi bởi VM, trong quá trình khởi tạo lớp.Các khối khởi tạo phiên bản không được biên dịch thành các phương thức riêng biệt; mã của chúng được sao chép vào mỗi phương thức khởi tạo, vì vậy chúng không thể được truy cập riêng lẻ, ngay cả khi phản chiếu.


7

default là một từ khóa được sử dụng làm công cụ sửa đổi quyền truy cập cho các phương thức và biến.
Việc sử dụng công cụ sửa đổi quyền truy cập này sẽ làm cho lớp, biến, phương thức hoặc hàm tạo của bạn có thể sử dụng được từ lớp hoặc gói riêng, nó cũng sẽ được đặt nếu không có công cụ sửa đổi truy cập nào.

  Access Levels
    Modifier    Class   Package Subclass  EveryWhere
    public        Y        Y       Y         Y
    protected     Y        Y       Y         N
    default       Y        Y       N         N
    private       Y        N       N         N

nếu bạn sử dụng mặc định trong một giao diện, bạn sẽ có thể triển khai một phương thức ở đó như ví dụ này

public interface Computer {    
    default void Start() {
        throw new UnsupportedOperationException("Error");
    }    
}

Tuy nhiên nó sẽ chỉ hoạt động từ phiên bản Java 8

Tài liệu chính thức

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


3

Xem tại đây để biết thêm chi tiết. Mặc định không phải là private / public / protected mà là một đặc tả truy cập hoàn toàn khác. Nó không được sử dụng rộng rãi và tôi thích cụ thể hơn nhiều trong các định nghĩa truy cập của mình.


3

chỉ định truy cập mặc định là gói. Các lớp có thể truy cập các thành viên của các lớp khác trong cùng một gói. nhưng bên ngoài gói, nó xuất hiện dưới dạng riêng tư


3

Dưới đây là trích dẫn về khả năng hiển thị ở cấp độ gói từ cuộc phỏng vấn với James Gosling, người tạo ra Java:

Bill Venners : Java có bốn cấp độ truy cập. Mặc định là gói. Tôi luôn tự hỏi liệu việc đặt quyền truy cập gói mặc định có thuận tiện không vì ba từ khóa mà mọi người từ C ++ đã biết là private, protected và public. Hoặc nếu bạn có một số lý do cụ thể mà bạn cảm thấy quyền truy cập gói phải là mặc định.

James Gosling : Một gói thường là một tập hợp những thứ được viết cùng nhau. Vì vậy, nói chung, tôi có thể làm một trong hai điều. Một là buộc bạn luôn phải đặt một từ khóa cung cấp cho bạn tên miền. Hoặc tôi có thể có một giá trị mặc định. Và câu hỏi đặt ra là, điều gì tạo nên một sự mặc định hợp lý? Và tôi có xu hướng làm những gì ít nguy hiểm nhất.

Vì vậy, công khai sẽ là một điều thực sự tồi tệ nếu để mặc định. Riêng tư có lẽ sẽ là một điều tồi tệ khi đặt mặc định, nếu chỉ vì mọi người thực sự không viết các phương thức riêng tư thường xuyên. Và điều tương tự với được bảo vệ. Và khi xem xét một loạt mã mà tôi có, tôi quyết định rằng thứ phổ biến nhất mà an toàn hợp lý nằm trong gói. Và C ++ không có từ khóa cho điều đó, bởi vì chúng không có khái niệm về gói.

Nhưng tôi thích nó hơn là khái niệm bạn bè, vì với bạn bè, bạn phải liệt kê tất cả bạn bè của mình là ai, và vì vậy nếu bạn thêm một lớp mới vào một gói, thì bạn thường phải đi đến tất cả các lớp học trong gói đó và cập nhật cho bạn bè của họ, điều mà tôi luôn thấy là hoàn toàn đau đớn ở mông.

Nhưng bản thân danh sách bạn bè gây ra một loại vấn đề lập phiên bản. Và vì vậy đã có khái niệm về một lớp học thân thiện. Và điều tuyệt vời là tôi đã đặt nó làm mặc định - tôi sẽ giải quyết vấn đề, vậy từ khóa nên là gì?

Trong một thời gian thực sự có một từ khóa thân thiện. Nhưng vì tất cả các từ khác đều bắt đầu bằng "P" nên nó là "dễ thương" với "PH." Nhưng điều đó chỉ ở đó có lẽ trong một ngày.

http://www.artima.com/intv/gosling2P.html


2

Cập nhật cách sử dụng từ khóa trong Java 8default : Như nhiều người khác đã lưu ý Khả năng hiển thị mặc định (không có từ khóa)

trường sẽ có thể truy cập từ bên trong cùng một gói mà lớp thuộc về.

Đừng nhầm lẫn với tính năng Java 8 mới ( Phương thức mặc định ) cho phép một giao diện cung cấp triển khai khi nó được gắn nhãn với defaulttừ khóa.

Xem: Công cụ sửa đổi quyền truy cập



-2

Trước hết, hãy để tôi nói một điều rằng không có thuật ngữ như "Access specifier" trong java. Chúng ta nên gọi mọi thứ là "Modifier". Như chúng ta biết rằng cuối cùng, tĩnh, đồng bộ hóa, bay hơi .... được gọi là bổ ngữ, ngay cả Công khai, riêng tư, bảo vệ, mặc định, trừu tượng cũng được gọi là bổ ngữ. Mặc định là một bổ ngữ như vậy mà sự tồn tại vật lý không có ở đó nhưng không có bổ trợ nào được đặt thì nó sẽ được coi là bổ ngữ mặc định.

Để biện minh cho điều này, hãy lấy một ví dụ:

public class Simple{  
    public static void main(String args[]){  
     System.out.println("Hello Java");  
    }  
}  

Đầu ra sẽ là: Hello Java

Bây giờ hãy thay đổi công khai thành riêng tư và xem bạn gặp lỗi trình biên dịch nào: Nó cho biết "Modifier private is not allow here" Kết luận ai đó có thể sai hoặc một số hướng dẫn có thể sai nhưng trình biên dịch không thể sai. Vì vậy, chúng ta có thể nói rằng không có thuật ngữ chỉ định truy cập trong java mọi thứ đều là bổ ngữ.


Câu đầu tiên là đúng, nhưng thực tế là một lớp bên ngoài không thể là riêng tư không chứng minh rằng không có thứ gì gọi là chỉ định truy cập trong Java.
Marquis of Lorne

@EJP Đây chỉ là một ví dụ. Những gì tôi đang nói là thuật ngữ chỉ định truy cập được sử dụng trong các ngôn ngữ khác như c, dot net, v.v. nhưng thuật ngữ kỹ thuật trong java cho điều này là bổ ngữ. Nếu bạn sử dụng nhật thực hay bất kỳ IDE khác mà bạn có thể thấy rằng tại thời điểm tạo lớp mới, chúng tôi được yêu cầu cung cấp bổ tên và trong danh sách mà họ cung cấp công cộng, tư nhân, trừu tượng, vv
Sagar Raut

Trong ví dụ của tôi, những gì tôi cố gắng nói rằng trình biên dịch đưa ra thông báo lỗi: không cho phép sửa đổi riêng tư, nó không đưa ra thông báo như trình xác định truy cập riêng tư không được phép. Vì vậy, các thuật ngữ kỹ thuật chúng ta nên nói là bổ ngữ trong java không truy cập specifier trong java
Sagar Raut
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.