在Java中,public、protected、package private和private之间有什么区别?
在Java中,是否有关于何时使用每个访问修饰符的明确规则,即默认的(包私有)、在Java中,public、protected、package private和private之间有什么区别?,java,private,public,protected,access-modifiers,Java,Private,Public,Protected,Access Modifiers,在Java中,是否有关于何时使用每个访问修饰符的明确规则,即默认的(包私有)、公共的、受保护的和私有的,同时使类和接口处理继承问题?可能对您有所帮助 等级 包裹 子类(相同包装) 子类(不同包装) 世界 public + + + + + 受保护 + + + + 无修饰语 + + + private + 简单规则。首先声明所有内容都是私有的。然后,随着需求的出现和设计的需要,向公众发展 在公开成员时,请自问是公开表示选择还是抽象选择。第一个问题是您希望避免的,因为它会引入太多对实际表示的依赖,而
公共的
、受保护的
和私有的
,同时使类
和接口
处理继承问题?可能对您有所帮助
等级 包裹 子类
(相同包装) 子类
(不同包装) 世界
public
+
+
+
+
+
受保护
+
+
+
+
无修饰语
+
+
+
private
+
简单规则。首先声明所有内容都是私有的。然后,随着需求的出现和设计的需要,向公众发展 在公开成员时,请自问是公开表示选择还是抽象选择。第一个问题是您希望避免的,因为它会引入太多对实际表示的依赖,而不是对其可观察的行为的依赖 作为一般规则,我试图通过子类化来避免重写方法实现;把逻辑搞砸太容易了。如果要重写抽象受保护的方法,请声明该方法
另外,在重写时使用@Override注释,以防止重构时出现问题。差异可以在已经提供的链接中找到,但使用哪一个通常归结为“最少知识原则”。只允许所需的最少可见性。(注意:我不是Java程序员,我是Perl程序员。Perl没有正式的保护措施,这也许就是为什么我对这个问题如此了解的原因:) 私有的 正如您所想,只有声明它的类才能看到它 包专用 它只能由声明它的包查看和使用。这是Java中的默认设置(有些人认为这是一个错误) 受保护的 包Private+可由子类或包成员查看 公开的 每个人都能看到 在我控制的代码之外可见。(虽然不是Java语法,但这对于本次讨论很重要) C++定义了一个称为“friend”的附加级别,您知道的越少越好 什么时候用什么?整个想法是封装以隐藏信息。您希望尽可能地对用户隐藏某些操作的细节。为什么?因为这样以后你就可以更改它们,而不会破坏任何人的代码。这使您可以优化、重构、重新设计和修复bug,而不用担心有人在使用您刚刚大修的代码 因此,经验法则是使事物只在必须的时候才可见。从private开始,只在需要时添加更多可见性。只公开用户必须知道的内容,你公开的每一个细节都会限制你重新设计系统的能力 如果您希望用户能够自定义行为,而不是公开内部构件,以便覆盖它们,那么最好将这些胆量塞进对象中,并公开该接口。这样他们就可以简单地插入一个新对象。例如,如果您正在编写一个CD播放机,并且希望“go find info about this CD”可以定制,而不是公开这些方法,那么您应该将所有这些功能放在它自己的对象中,只公开您的对象getter/setter。通过这种方式,吝啬暴露自己的胆量会鼓励良好的组合和关注点的分离 就个人而言,我只坚持“私人”和“公共”。许多面向对象语言都有这样的功能。“受保护”可能很方便,但实际上是个骗局。一旦一个接口不仅仅是私有的,它就超出了你的控制范围,你必须去寻找其他人的代码来找到它的用途 这就是“出版”这个概念的由来。更改一个接口(重构它)需要找到使用它的所有代码,并对其进行更改。如果接口是私有的,那么没有问题。如果它受到保护,你必须找到你所有的子类。如果它是公共的,你必须找到所有使用你的代码的代码。有时这是可能的,例如,如果您正在编写仅供内部使用的公司代码,那么接口是否是公共的并不重要。您可以从公司存储库中获取所有代码。但是如果一个接口被“发布”,如果有代码在你的控制之外使用它,那么你就被套住了。您必须支持该接口,否则可能会破坏代码。即使是受保护的接口也可以被认为是已发布的(这就是为什么我不用担心受保护的接口)
许多语言发现公共/受保护/私有的层级性质过于局限,不符合现实。为此,有了a的概念,但那是另一个节目。大卫的回答提供了每个访问修饰符的含义。至于何时使用每个类,我建议公开所有用于外部使用的类和每个类的方法(其API),其他所有内容都是私有的 随着时间的推移,您将了解何时将某些类打包为私有,何时声明某些受保护的方法以供在子类中使用。 。。。。 受保护:受保护的访问修饰符有点复杂,可以说是默认访问修饰符的超集。就同一包中的访问权限而言,受保护成员与默认成员相同。区别在于,受保护的成员也可以被声明成员的类的子类访问,这些子类位于父类所在的包之外 但这些受保护的成员“只能通过继承在包外访问”“。也就是说,您可以直接访问其他包中存在的子类中某个类的受保护成员,就像该成员存在于子类本身一样。但是,该受保护成员将无法通过使用父类在包外的子类中访问。”
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
+—-———————————————+————————————+———————————+
| | Same | Different |
| | Package | Packages |
+—————————————————+————————————+———————————+
| private | D | |
+—————————————————+————————————+———————————+
| package-private | | |
| (no modifier) | D R I | |
+—————————————————+————————————+———————————+
| protected | D R I | I |
+—————————————————+————————————+———————————+
| public | D R I | R I |
+—————————————————+————————————+———————————+
____________________________________________________________________
| 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 | ✔ | ✘ | ✘ | ✘
____________________________________________________________________
package fatherpackage;
public class Father
{
}
-------------------------------------------
package sonpackage;
public class Son extends Father
{
}
package fatherpackage;
public class Father
{
protected void foo(){}
}
package fatherpackage;
public class SomeClass
{
public void someMethod(Father f, Son s)
{
f.foo();
s.foo();
}
}
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();
}
}
package fatherpackage;
public class Son extends Father
{
public void sonMethod(Father f)
{
f.foo();
}
}
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
}
}
String name = "john";
public int age(){
return age;
}
Public class Details{
private String name;
public void setName(String n){
this.name = n;
}
public String getName(){
return this.name;
}
}
public void cal(){
}
class Van{
protected boolean speed(){
}
}
class Car{
boolean speed(){
}
}
// 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
}
}
// 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();
}
}
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
}
}
// 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();
}
}
╔═════════════╦═══════╦═════════╦══════════╦═══════╗
║ 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 ║
╚═════════════╩═══════╩═════════╩══════════╩═══════╝
Outside world -> Package (SecurityEntryClass ---> Package private classes)