在 Java 中,是否有关于何时使用每个访问修饰符的明确规则,即默认(包私有)、public
和protected
,private
同时进行class
和interface
处理继承?
30 回答
官方教程可能对你有些用处。
班级 | 包裹 | 子类 (相同的 pkg) |
子类 (差异包) |
世界 | |
---|---|---|---|---|---|
public |
+ | + | + | + | + |
protected |
+ | + | + | + | |
没有修饰符 | + | + | + | ||
private |
+ |
+:可访问
空白:不可访问
(警告:我不是 Java 程序员,我是 Perl 程序员。Perl 没有正式的保护措施,这也许就是为什么我能很好理解这个问题的原因 :))
私人的
就像你想的那样,只有声明它的类才能看到它。
包私人
它只能被声明它的包看到和使用。这是 Java 中的默认设置(有些人认为这是一个错误)。
受保护
Package Private + 可以被子类或包成员看到。
上市
每个人都可以看到它。
发表
在我控制的代码之外可见。(虽然不是 Java 语法,但它对本次讨论很重要)。
C++ 定义了一个称为“朋友”的附加级别,您对此了解得越少越好。
什么时候应该使用什么?整个想法是封装以隐藏信息。您希望尽可能地向用户隐藏有关如何完成某事的细节。为什么?因为那样你就可以在以后更改它们而不会破坏任何人的代码。这使您可以优化、重构、重新设计和修复错误,而不必担心有人在使用您刚刚大修过的代码。
因此,经验法则是使事物仅在它们必须显示的情况下可见。从私有开始,仅根据需要添加更多可见性。只公开用户必须知道的内容,你公开的每一个细节都会限制你重新设计系统的能力。
如果您希望用户能够自定义行为,而不是公开内部结构以便他们可以覆盖它们,那么将这些胆量放入一个对象并公开该接口通常是一个更好的主意。这样他们就可以简单地插入一个新对象。例如,如果您正在编写一个 CD 播放器并希望“查找有关此 CD 的信息”有点可定制,而不是将这些方法公开,您会将所有这些功能放入它的对象中,并且只公开您的对象 getter/setter。通过这种方式,对暴露你的胆量吝啬鼓励良好的组合和关注点分离
我只坚持“私人”和“公共”。许多 OO 语言就是这样。“受保护”可能很方便,但它是个骗子。一旦接口不再是私有的,它就超出了你的控制范围,你必须去查看其他人的代码才能找到用途。
这就是“发布”的想法出现的地方。更改接口(重构它)要求您找到所有正在使用它的代码并对其进行更改。如果接口是私有的,那没问题。如果它受到保护,您必须找到所有子类。如果它是公开的,你必须去查找所有使用你的代码的代码。有时这是可能的,例如,如果您正在处理仅供内部使用的公司代码,那么接口是否公开并不重要。您可以从公司存储库中获取所有代码。但是,如果一个接口被“发布”了,如果有代码在你的控制之外使用它,那么你就完蛋了。您必须支持该接口或冒着破坏代码的风险。甚至受保护的接口也可以被视为已发布(这就是我不这样做的原因
许多语言发现 public/protected/private 的等级性质过于局限且不符合现实。为此,有一个trait class的概念,但那是另一回事。
这是一个更好的表格版本,它还包括一个模块列。
解释
私有成员 (
i
)只能在声明的同一类中访问。没有访问修饰符( )的成员
j
只能在同一包中的类中访问。受保护的成员 (
k
) 可在同一包中的所有类以及其他包中的子类中访问。所有类都可以访问公共成员 ( )(除非它驻留在不导出声明它的包的模块中)。
l
选择哪个修饰符?
访问修饰符是一种帮助您防止意外破坏封装(*)的工具。问问自己,您是否希望该成员成为类、包、类层次结构的内部或根本不是内部的,并相应地选择访问级别。
例子:
- 一个字段
long internalCounter
可能应该是私有的,因为它是可变的并且是一个实现细节。 - 一个只应该在工厂类(在同一个包中)实例化的类应该有一个包受限的构造函数,因为它不应该直接从包外部调用它。
void beforeRender()
应该保护在渲染之前调用并用作子类中的挂钩的内部方法。- 从 GUI 代码调用的
void saveGame(File dst)
方法应该是公共的。
(*)究竟什么是封装?
____________________________________________________________________
| 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 | ✔ | ✘ | ✘ | ✘
____________________________________________________________________
简单的规则。首先将所有内容声明为私有。然后随着需求的出现和设计的需要向公众发展。
当公开成员时,问问自己你是公开表示选择还是抽象选择。第一个是您要避免的,因为它会引入对实际表示的过多依赖,而不是对其可观察行为的依赖。
作为一般规则,我尽量避免通过子类化来覆盖方法实现;太容易搞砸逻辑了。如果您打算覆盖抽象受保护方法,请声明它。
此外,在重写时使用 @Override 注释以防止在重构时破坏。
它实际上比简单的网格显示要复杂一些。网格告诉您是否允许访问,但究竟是什么构成了访问?此外,访问级别以复杂的方式与嵌套类和继承交互。
“默认”访问(由没有关键字指定)也称为package-private。例外:在接口中,没有修饰符意味着公共访问;禁止使用 public 以外的修饰符。枚举常量总是公开的。
概括
是否允许使用此访问说明符访问成员?
- 成员是
private
:仅当成员与调用代码在同一类中定义时。 - 成员是包私有的:仅当调用代码在成员的直接封闭包中时。
- 成员是
protected
:相同的包,或者如果成员是在包含调用代码的类的超类中定义的。 - 会员是
public
:是的。
访问说明符适用于什么
局部变量和形式参数不能使用访问说明符。由于根据范围规则,它们本质上是外部无法访问的,因此它们实际上是私有的。
对于顶级范围内的类,只public
允许使用包私有。这种设计选择可能是因为protected
并且private
在包级别是多余的(没有包的继承)。
类成员(构造函数、方法和静态成员函数、嵌套类)上的所有访问说明符都是可能的。
相关:Java 类可访问性
命令
访问说明符可以严格排序
公共>受保护>包私有>私有
意思是public
提供最多的访问,private
最少的。对私有成员的任何引用也对包私有成员有效;任何对包私有成员的引用在受保护成员上都是有效的,依此类推。(授予对同一包中其他类的受保护成员的访问权限被认为是错误的。)
笔记
- 一个类的方法可以访问同一个类的其他对象的私有成员。更准确地说,C 类的方法可以在 C 的任何子类的对象上访问 C 的私有成员。Java 不支持按实例限制访问,仅支持按类。(与 Scala 相比,后者使用 . 支持它
private[this]
。) - 您需要访问构造函数来构造对象。因此,如果所有构造函数都是私有的,则只能由存在于类中的代码(通常是静态工厂方法或静态变量初始值设定项)来构造该类。对于包私有或受保护的构造函数也是如此。
- 仅具有私有构造函数也意味着该类不能在外部子类化,因为 Java 要求子类的构造函数隐式或显式调用超类构造函数。(但是,它可以包含一个嵌套类来继承它。)
内部类
您还必须考虑嵌套范围,例如内部类。复杂性的一个例子是内部类有成员,它们本身可以使用访问修饰符。所以你可以有一个带有公共成员的私有内部类;会员可以访问吗?(见下文。)一般规则是查看范围并递归思考以查看您是否可以访问每个级别。
但是,这相当复杂,有关详细信息,请参阅 Java 语言规范。(是的,过去存在编译器错误。)
要了解它们如何相互作用,请考虑这个例子。可以“泄露”私有内部类;这通常是一个警告:
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();
}
}
编译器输出:
Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
Example.leakPrivateClass().secretMethod(); // error
^
1 error
一些相关问题:
根据经验:
private
: 类范围。default
(或package-private
):包范围。protected
:package scope + child
(就像包,但我们可以从不同的包中对其进行子类化)。protected 修饰符始终保持“父子”关系。public
: 无处不在。
因此,如果我们将访问权限分为三种权限:
- (D) 直接(从同一类中的方法调用,或通过“this”语法调用)。
- (R)eference(使用对类的引用或通过“点”语法调用方法)。
- (I) 继承(通过子类化)。
然后我们有这个简单的表:
+—-———————————————+————————————+———————————+
| | Same | Different |
| | Package | Packages |
+—————————————————+————————————+———————————+
| private | D | |
+—————————————————+————————————+———————————+
| package-private | | |
| (no modifier) | D R I | |
+—————————————————+————————————+———————————+
| protected | D R I | I |
+—————————————————+————————————+———————————+
| public | D R I | R I |
+—————————————————+————————————+———————————+
简而言之
public
: 随处可见。protected
:可由同一包的类和位于任何包中的子类访问。- 默认值(未指定修饰符):可由同一包的类访问。
private
: 只能在同一个类中访问。
Java 中最容易被误解的访问修饰符是protected
. 我们知道它类似于默认修饰符,但有一个例外,子类可以看到它。但是怎么做?这是一个希望澄清混淆的示例:
假设我们有 2 个类;
Father
和Son
,每个都在自己的包中:package fatherpackage; public class Father { } ------------------------------------------- package sonpackage; public class Son extends Father { }
让我们添加一个受保护的方法
foo()
到Father
.package fatherpackage; public class Father { protected void foo(){} }
该方法
foo()
可以在 4 种上下文中调用:在位于
foo()
定义(fatherpackage
)的同一包中的类中:package fatherpackage; public class SomeClass { public void someMethod(Father f, Son s) { f.foo(); s.foo(); } }
在子类中,在当前实例上通过
this
orsuper
:package sonpackage; public class Son extends Father { public void sonMethod() { this.foo(); super.foo(); } }
在类型为同一类的引用上:
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(); } }
在类型为父类的引用上,并且它位于定义的包内
foo()
(fatherpackage
) [这可以包含在上下文编号中。1]:package fatherpackage; public class Son extends Father { public void sonMethod(Father f) { f.foo(); } }
以下情况无效。
在类型为父类且位于定义的包之外
foo()
的引用上 (fatherpackage
):package sonpackage; public class Son extends Father { public void sonMethod(Father f) { f.foo(); // compilation error } }
子类的包中的非子类(子类从其父类继承受保护的成员,并使它们对非子类私有):
package sonpackage; public class SomeClass { public void someMethod(Son s) throws Exception { s.foo(); // compilation error } }
私人的
- 方法、变量和构造函数
声明为私有的方法、变量和构造函数只能在声明的类本身内访问。
- 类和接口
私有访问修饰符是限制性最强的访问级别。类和接口不能是私有的。
笔记
如果类中存在公共 getter 方法,则可以在类外部访问声明为私有的变量。在超类中声明为protected的变量、方法和构造函数只能被其他包中的子类或受保护成员类的包中的任何类访问。
受保护
- 类和接口
protected 访问修饰符不能应用于类和接口。
方法、字段可以声明为受保护,但是接口中的方法和字段不能声明为受保护。
笔记
受保护的访问使子类有机会使用辅助方法或变量,同时防止不相关的类尝试使用它。
上市
可以从任何其他类访问声明为公共的类、方法、构造函数、接口等。
因此,可以从属于 Java Universe 的任何类访问在公共类中声明的字段、方法、块。
- 不同的包
但是,如果我们试图访问的公共类在不同的包中,那么仍然需要导入公共类。
因为类继承,一个类的所有公共方法和变量都被它的子类继承。
默认 - 无关键字:
默认访问修饰符意味着我们不会为类、字段、方法等显式声明访问修饰符。
- 在同一个包内
没有任何访问控制修饰符声明的变量或方法可用于同一包中的任何其他类。接口中的字段是隐式的 public static final ,接口中的方法默认是 public 的。
笔记
我们无法覆盖静态字段。如果您尝试覆盖它不会显示任何错误,但它不能正常工作。
相关答案
参考链接
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm
可以在已经提供的链接中找到差异,但使用哪一个通常归结为“最少知识原则”。只允许所需的最低可见性。
Private : 仅限上课
默认(无修饰符):对类和包的有限访问
受保护:对类、包和子类的访问受限(包内部和外部)
Public:类、包(全部)和子类都可以访问...简而言之,无处不在。
访问修饰符用于限制多个级别的访问。
Public:它基本上就像你可以从任何类访问一样简单,无论它是否在同一个包中。
要访问,如果您在同一个包中,您可以直接访问,但如果您在另一个包中,则可以创建该类的对象。
默认值:可以从任何包类在同一个包中访问它。
要访问,您可以创建类的对象。但是你不能在包之外访问这个变量。
受保护:您可以访问同一包中的变量以及任何其他包中的子类。所以基本上它是默认+继承的行为。
要访问基类中定义的受保护字段,您可以创建子类的对象。
私有: 可以在同一个类中访问。
在非静态方法中,由于此引用(也在构造函数中),您可以直接访问,但要在静态方法中访问,您需要创建类的对象。
Java 中的访问修饰符。
Java 访问修饰符用于在 Java 中提供访问控制。
1. 默认:
只能访问同一包中的类。
例如,
// 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
}
}
这种访问比公共的和受保护的更受限制,但比私有的限制更少。
2.公开
可以从任何地方访问。(全球访问)
例如,
// 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();
}
}
输出:你好
3.私人
只能在同一个班级内访问。
如果您尝试访问另一个类的私有成员,则会引发编译错误。例如,
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.受保护
只能访问同一包中的类和子类
例如,
// 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();
}
}
输出:你好
对包可见。默认。不需要修饰符。
仅对类可见(私有)。
对世界可见(公开)。
对包和所有子类可见(受保护)。
可以在不调用任何修饰符的情况下声明变量和方法。默认示例:
String name = "john";
public int age(){
return age;
}
私有访问修饰符 - 私有:
声明为私有的方法、变量和构造函数只能在声明的类本身内访问。private 访问修饰符是最严格的访问级别。类和接口不能是私有的。
如果类中存在公共 getter 方法,则可以在类外部访问声明为私有的变量。
使用 private 修饰符是对象封装自身并向外界隐藏数据的主要方式。
例子:
Public class Details{
private String name;
public void setName(String n){
this.name = n;
}
public String getName(){
return this.name;
}
}
公共访问修饰符 - public:
可以从任何其他类访问声明为 public 的类、方法、构造函数、接口等。因此,可以从属于 Java 世界的任何类访问在公共类中声明的字段、方法、块。
但是,如果我们试图访问的公共类在不同的包中,那么仍然需要导入公共类。
因为类继承,一个类的所有公共方法和变量都被它的子类继承。
例子:
public void cal(){
}
受保护的访问修饰符 - 受保护:
在超类中声明为受保护的变量、方法和构造函数只能由另一个包中的子类或受保护成员类的包中的任何类访问。
protected 访问修饰符不能应用于类和接口。方法、字段可以声明为受保护,但是接口中的方法和字段不能声明为受保护。
受保护的访问使子类有机会使用辅助方法或变量,同时防止不相关的类尝试使用它。
class Van{
protected boolean speed(){
}
}
class Car{
boolean speed(){
}
}
public - 可从应用程序中的任何位置访问。
默认- 可从包中访问。
protected - 可从其他包中的包和子类访问。以及
private - 只能从它的类访问。
.... Protected:受保护的访问修饰符有点棘手,您可以说它是默认访问修饰符的超集。就同一包中的访问而言,受保护的成员与默认成员相同。不同之处在于,受保护的成员也可以被声明该成员的类的子类访问,这些子类位于父类所在的包之外。
但是这些受保护的成员“只能通过继承在包外访问”。即,您可以直接访问其他包中存在的子类中的类的受保护成员,就好像该成员存在于子类本身中一样。但是,通过使用父类的引用,将无法在包外的子类中访问该受保护的成员。……
大卫的回答提供了每个访问修饰符的含义。至于何时使用每一个,我建议将所有类和每个类的用于外部使用的方法(其 API)公开,并将其他所有内容设为私有。
随着时间的推移,您将了解何时将某些类设为包私有以及何时声明某些受保护的方法以供在子类中使用。
Public Protected Default 和 private 是访问修饰符。
它们用于封装,或隐藏和显示类的内容。
- 类可以是公共的或默认的
- 类成员可以是公共的、受保护的、默认的或私有的。
Private 在类之外不可访问 Default 只能在包中访问。在包以及扩展它的任何类中受保护。公众对所有人开放。
通常,成员变量是私有的,但成员方法是公共的。
注意:这只是对已接受答案的补充。
这与 Java Access Modifiers相关。
Java 访问修饰符指定哪些类可以访问给定类及其字段、构造函数和方法。可以为类、其构造函数、字段和方法单独指定访问修饰符。Java 访问修饰符在日常用语中有时也称为 Java 访问说明符,但正确的名称是 Java 访问修饰符。类、字段、构造函数和方法可以具有四种不同的 Java 访问修饰符之一:
- 项目清单
- 私人的
- 默认(包)
- 受保护
- 上市
从控制对班级成员的访问权限教程:
访问级别修饰符确定其他类是否可以使用特定字段或调用特定方法。有两个级别的访问控制:
- 在顶层——public 或 package-private(没有显式修饰符)。
- 在成员级别——public、private、protected 或 package-private(无显式修饰符)。
可以使用修饰符 public 声明一个类,在这种情况下,该类对任何地方的所有类都是可见的。如果一个类没有修饰符(默认值,也称为包私有),则它只在自己的包中可见
下表显示了对每个修饰符允许的成员的访问。
╔═════════════╦═══════╦═════════╦══════════╦═══════╗ ║ 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 ║ ╚═════════════╩═══════╩═════════╩══════════╩═══════╝
第一个数据列指示类本身是否有权访问由访问级别定义的成员。如您所见,一个类总是可以访问它自己的成员。第二列指示与该类位于同一包中的类(无论其父级如何)是否可以访问该成员。第三列表示在此包外声明的类的子类是否可以访问该成员。第四列表示是否所有类都可以访问该成员。
访问级别以两种方式影响您。首先,当您使用来自其他来源的类时,例如 Java 平台中的类,访问级别决定了您自己的类可以使用这些类的哪些成员。其次,当你编写一个类时,你需要决定你的类中的每个成员变量和每个方法应该有什么访问级别。
我经常意识到,通过创建现实世界的类比,可以记住任何语言的基本概念。这是我理解 Java 中访问修饰符的类比:
假设您是大学的学生,并且您有一个朋友周末来拜访您。假设校园中央有一尊大学创始人的大雕像。
当你把他带到校园时,你和你的朋友首先看到的就是这座雕像。这意味着任何走进校园的人都可以在未经大学许可的情况下观看雕像。这使雕像成为PUBLIC。
接下来,您想将您的朋友带到您的宿舍,但为此您需要将他注册为访客。这意味着他获得了进入校园内各种建筑物的通行证(与您的相同)。这将使他的访问卡成为PROTECTED。
您的朋友想登录校园 WiFi,但没有任何凭据。他可以上网的唯一方法是您与他分享您的登录信息。(请记住,每个上大学的学生都拥有这些登录凭据)。这将使您的登录凭据为NO MODIFIER。
最后,您的朋友想阅读您在网站上发布的学期进度报告。但是,每个学生都有自己的个人登录名来访问校园网站的这一部分。这将使这些凭据成为PRIVATE。
希望这可以帮助!
当您考虑访问修饰符时,只需以这种方式考虑它(适用于变量和方法):
public
--> 可从任何地方
private
访问 --> 只能在声明它的同一个类中访问
现在,当涉及到default
和protected
default
--> 不存在访问修饰符关键字。这意味着它在类的包中严格可用。在该软件包之外的任何地方都无法访问它。
protected
--> 比相同的包类稍微宽松一些default
,除了相同的包类之外,它可以被声明的包之外的子类访问。
我的两分钱:)
私人的:
类 ->顶级类不能是私有的。内部类可以是私有的,可以从同一个类访问。
实例变量 ->只能在类中访问。不能在课外访问。
包私有:
类 ->顶级类可以是包私有的。它只能从同一个包中访问。不是来自子包,不是来自外部包。
实例变量 ->可从同一个包访问。不是来自子包,不是来自外部包。
受保护:
类 ->无法保护顶级类。
实例变量 ->只能在同一个包或子包中访问。扩展类时只能在包外访问。
上市:
类 ->可从包/子包/另一个包访问
实例变量 ->可从包/子包/另一个包访问
这里有详细解答
https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md
这完全是关于封装(或者正如乔菲利普斯所说,最少的知识)。
从最严格的(私人)开始,看看您以后是否需要限制较少的修饰符。
我们都使用方法和成员修饰符,如 private、public ......但很少有开发人员做的一件事是使用包来逻辑组织代码。
例如:您可以将敏感的安全方法放在“安全”包中。然后在这个包中放置一个访问一些安全相关代码但保持其他安全类包私有的公共类。因此,其他开发人员将只能使用此包外部的公共可用类(除非他们更改修饰符)。这不是一项安全功能,但会指导使用。
Outside world -> Package (SecurityEntryClass ---> Package private classes)
另一件事是,相互依赖很多的类可能最终在同一个包中,如果依赖关系太强,最终可能会被重构或合并。
相反,如果您将所有内容都设置为公开,则将不清楚应该或不应该访问什么,这可能会导致编写大量 javadoc(它不会通过编译器强制执行任何操作......)。
上市
如果一个类成员是用 public 声明的,那么它可以从任何地方访问
受保护
如果一个类成员用关键字protected声明,那么它可以从同一个类成员、同一个包内的外部类成员和继承的类成员访问。如果类成员受保护,则不能从外部包类访问它,除非继承外部包类,即扩展另一个包超类。但是受保护的类成员始终可用于相同的包类,不管是否继承了相同的包类
默认
在 Java 中,默认不是访问修饰符关键字。如果声明类成员时没有任何访问修饰符关键字,那么在这种情况下,它被视为默认成员。默认类成员始终对相同的包类成员可用。但是即使外部类是与受保护成员不同的子类,外部包类成员也不能访问默认类成员
私人的
如果一个类成员是用关键字protected声明的,那么在这种情况下,它只对相同的类成员可用
当您不希望您的变量/方法/类在该类之外可见时,请使用私有。当您希望只有此类的孩子可以使用该变量时,请使用 protected。当您希望变量/类/方法应该可以从任何地方访问时,请使用 public。当您希望您的变量/类/方法仅在该包内使用时,请使用包私有。
Java 中的访问说明符:Java 中有 4 种访问说明符,即 private、package-private(默认)、protected 和 public,按访问顺序递增。
Private:当你正在开发某个类并且你希望这个类的成员不暴露在这个类之外时,你应该将它声明为私有的。私有成员只能在定义它们的类中访问,即封闭类。可以在“this”引用以及包含这些成员的其他类实例上访问私有成员,但只能在此类的定义内访问。
包私有(默认):除了下面描述的访问之外,此访问说明符将提供由私有访问说明符指定的访问权限。
当您正在开发某个包以及其中的某个类(例如 Class1)时,您可以使用默认(无需明确提及)访问说明符,将类中的成员公开给(相同)包中的其他类。在这些其他类中(在同一个包中),您可以访问 Class1 实例上的这些默认成员。您还可以在 Class1 的子类中访问这些默认成员,例如 Class2(在此引用上或在 Class1 的实例上或在 Class2 的实例上)。
基本上,在同一个包中,您可以直接访问类实例上的默认成员或子类中的“this”引用。
protected:除了下面描述的访问之外,此访问说明符将提供包私有访问说明符指定的访问权限。
当您正在开发某个包以及其中的某个类(例如 Class1)时,如果您不希望在您的包之外访问该成员(例如在一般而言,您的包(即使用您的 API 的客户端),但是您希望例外并仅在客户端编写扩展 Class1 的 Class2 时才允许访问此成员。因此,一般来说,受保护的成员可以在派生类(即 Class2)中的“this”引用上访问,也可以在 Class2 的显式实例上访问。
请注意:
- 如果您尝试在 Class1 的显式实例上访问它,您将无法访问 Class2 中 Class1 的继承的受保护成员,尽管它是在其中继承的。
- 当您在扩展 Class2 的相同/不同包中编写另一个类 Class3 时,来自 Class1 的受保护成员将可以在此引用以及 Class3 的显式实例上访问。这对于任何扩展的层次结构都是如此,即受保护的成员仍然可以在此引用或扩展类的实例上访问。请注意,在 Class3 中,如果您创建 Class2 的实例,那么您将无法从 Class1 访问受保护的成员,尽管它是继承的。
所以底线是,受保护的成员可以在其他包中访问,只有当这个其他包中的某个类扩展包含这个受保护成员的类并且在“this”引用或扩展类的显式实例上访问受保护成员时,在扩展的定义内班级。
public:除了下面描述的访问之外,此访问说明符将提供受保护访问说明符指定的访问权限。
当您正在开发某个包并因此开发其中的某个类(例如 Class1)时,如果您希望该成员可以在其他包中创建的 Class1 实例上的其他包中访问,那么您应该对 Class1 中的数据成员使用公共访问说明符包裹。基本上,当您打算无条件地将数据成员公开给世界时,应该使用此访问说明符。