在Java中,在创建类和接口以及处理继承时,是否有明确的规则来确定何时使用每个访问修饰符,即默认的(包私有)、公共的、受保护的和私有的?
当前回答
这是该表的一个更好的版本,其中还包括一个模块列。
解释
私有成员(i)只能在声明的同一类中访问。没有访问修饰符(j)的成员只能在同一包中的类中访问。受保护的成员(k)可以在同一包中的所有类和其他包中的子类中访问。公共成员(l)对所有类都是可访问的(除非它驻留在不导出声明它的包的模块中)。
要选择哪个修饰符?
访问修饰符是一种帮助您防止意外破坏封装(*)的工具。问问自己,您是否希望成员是类、包、类层次结构的内部成员,或者根本不是内部成员,并相应地选择访问级别。
示例:
长字段internalCounter可能应该是私有的,因为它是可变的,并且是实现细节。只应在工厂类中实例化的类(在同一个包中)应具有包限制构造函数,因为不可能从包外部直接调用它。应保护在呈现之前调用并用作子类中钩子的内部void beforeRender()方法。从GUI代码调用的void saveGame(File dst)方法应该是公共的。
(*)封装到底是什么?
其他回答
访问修饰符用于限制多个级别的访问。
公共:它基本上和您可以从任何类访问一样简单,无论它是否在同一个包中。
若要访问同一个包,可以直接访问,但若您在另一个包中,则可以创建类的对象。
默认值:它可以在同一个包中从任何一类包访问。
要访问,可以创建类的对象。但不能在包外访问此变量。
受保护:您可以访问同一包中的变量以及任何其他包中的子类。所以基本上它是默认+继承的行为。
要访问基类中定义的受保护字段,可以创建子类的对象。
私有:可以在同一类中访问。
在非静态方法中,由于该引用(也在构造函数中),您可以直接访问,但要在静态方法中访问,您需要创建类的对象。
我的两分钱:)
私人:
class->顶级类不能是私有的。内部类可以是私有的,可以从同一类访问。
实例变量->只能在类中访问。无法在类外部访问。
包专用:
class->顶级类可以是包专用的。它只能从同一个包访问。不是来自子包装,不是来自外包装。
实例变量->可从同一包访问。不是来自子包装,不是来自外包装。
受保护的:
class->无法保护顶级类。
实例变量->只能在同一包或子包中访问。扩展类时只能在包外部访问。
公众:
类->可从包/子包/另一个包访问
实例变量->可从包/子包/另一个包访问
下面是详细的答案
https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md
对于初学者来说,考虑这个例子可能会有所帮助;
考虑到我在foo包中开发了MyClass,它有一个很棒的方法,名为print,您有兴趣调用它(它可能是一个方法或属性)
package foo; // I am in foo
public class MyClass {
private void print() { //This is private
System.out.println("I can print!");
}
}
您已经开发了YourClass的bar包,您有兴趣使用MyClass#print
package bar; \\You are not in same package as me
import foo.MyClass;
public class YourClass {
void test() {
MyClass myClass = new MyClass();
myClass.print();
}
}
您的代码未编译,并且出现错误。方法print()对于类型MyClass未定义
你来找我:
你:我想用你的方法,但它是私人的。你能公开吗?我:不,我不想让别人使用你:我是你的朋友,至少让我不要让别人使用它。我:好的,我将删除私有关键字。我的访问修饰符将是默认的或私有的包。因为你们是我的朋友,你们必须和我在同一个包裹里。所以你们必须来到我的包裹里。我的意思是确切的包,甚至不是子包。
然后MyClass将
package foo;
public class MyClass {
void print() { //No access modifier means default or package-private
System.out.println("I can print!");
}
}
YourClass将是:
package foo;//You come to my package
public class YourClass {
void test() {
MyClass myClass = new MyClass();
myClass.print();
}
}
不考虑这个:你又来找我了
你:我的老板告诉我我不能改变我的包(在实际世界中,你不能改变你的包以使用其他类方法)我:还有另一种方法,如果你扩展我,我使print()受到保护,那么无论你是否更改包,你都可以使用它。(因此,子类将始终允许您访问我的方法)。
这是我的班级
package foo;
protected class MyClass { // it is now protected
protected void print() {
System.out.println("I can print!");
}
}
这是YourClass
package bar; // You are on your own package
import foo.MyClass;
public class YourClass extends MyClass {
void test() {
//You initiate yourself! But as you extend me you can call my print()
YourClass yourClass = new YourClass();
yourClass.print();
}
}
您可能已经注意到,通过使一个方法受到保护,所有其他类都可以通过扩展它来使用它,您无法轻松控制如何使用它。这在java17中通过引入密封和许可词来解决。因此,您可以定义哪些类可以扩展您。类似于公共密封类MyClass允许YourClass参见Java17中的密封类是什么?有关详细信息
它实际上比简单的网格显示要复杂一些。网格告诉是否允许访问,但访问到底由什么构成?此外,访问级别以复杂的方式与嵌套类和继承交互。
“默认”访问(由缺少关键字指定)也称为包专用。异常:在接口中,没有修饰符表示公共访问;禁止公共以外的修饰语。枚举常量始终是公共的。
总结
是否允许使用此访问说明符访问成员?
成员是私有的:仅当成员与调用代码在同一类中定义时。成员是包专用的:仅当调用代码位于成员的直接封装包内时。成员受保护:相同的包,或者如果成员是在包含调用代码的类的超类中定义的。成员公开:是的。
访问说明符应用于什么
局部变量和形式参数不能采用访问说明符。由于根据范围界定规则,外部无法访问它们,因此它们实际上是私有的。
对于顶级作用域中的类,只允许public和package private。这种设计选择大概是因为受保护和私有在包级别是冗余的(没有包的继承)。
所有访问说明符都可以在类成员(构造函数、方法和静态成员函数、嵌套类)上使用。
相关:Java类可访问性
顺序
访问说明符可以严格排序
public>protected>package private>private
这意味着公共提供的访问最多,而私人提供的访问最少。对私有成员的任何引用对包私有成员也是有效的;对包私有成员的任何引用都对受保护成员有效,依此类推。(将受保护成员的访问权限授予同一包中的其他类被认为是错误的。)
笔记
允许类的方法访问同一类的其他对象的私有成员。更准确地说,类C的方法可以访问C的任何子类的对象上的C的私有成员。Java不支持仅通过类而通过实例限制访问。(与Scala相比,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
一些相关问题:
包私有类内的Java方法可访问性?
Public Protected Default和private是访问修饰符。
它们用于封装,或隐藏和显示类的内容。
类可以是公共的或默认的类成员可以是公共的、受保护的、默认的或私有的。
课堂外无法访问私人课程默认值只能在包中访问。在包以及扩展它的任何类中受到保护。公众对所有人开放。
通常,成员变量被定义为私有的,但成员方法是公共的。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap