在Java中,在创建类和接口以及处理继承时,是否有明确的规则来确定何时使用每个访问修饰符,即默认的(包私有)、公共的、受保护的和私有的?


当前回答

官方教程可能对您有所帮助。


Class Package Subclass
(same pkg)
Subclass
(diff pkg)
World
public + + + + +
protected + + + +
no modifier + + +
private +

+:可访问空白:不可访问

其他回答

Java中最容易被误解的访问修饰符是受保护的。我们知道它类似于默认修饰符,只有一个例外,子类可以看到它?这里有一个例子,希望能澄清这一困惑:

假设我们有2个类;父亲和儿子,每个人都有自己的包装:包父包;公共课父亲{}-------------------------------------------package-sonpackage;公共课儿子延伸父亲{}让我们向Father添加一个受保护的方法foo()。包父包;公共课父亲{受保护的void foo(){}}方法foo()可以在4种上下文中调用:在位于定义foo()的同一包中的类内(父包):包父包;公共类SomeClass{公共无效方法(父f,子s){f.foo();s.foo();}}在子类内部,在当前实例上通过this或super:package-sonpackage;公共课儿子延伸父亲{public void sonMethod(){this.foo();super.foo();}}在类型为同一类的引用上:包父包;公共课父亲{公共无效父方法(父f){f.foo();//即使foo()是私有的,也有效}}-------------------------------------------package-sonpackage;公共课儿子延伸父亲{公共无效sonMethod(Sons){s.foo();}}在一个类型为父类的引用上,该引用位于定义foo()的包内(父包)[这可以包含在上下文1中]:包父包;公共课儿子延伸父亲{公共无效sonMethod(父f){f.foo();}}以下情况无效。在类型为父类且位于定义foo()的包(父包)外部的引用上:package-sonpackage;公共课儿子延伸父亲{公共无效sonMethod(父f){f.foo();//编译错误}}子类包中的非子类(子类从其父类继承受保护的成员,并使其成为非子类的私有成员):package-sonpackage;公共类SomeClass{public void someMethod(儿子)引发异常{s.foo();//编译错误}}

我的两分钱:)

私人:

class->顶级类不能是私有的。内部类可以是私有的,可以从同一类访问。

实例变量->只能在类中访问。无法在类外部访问。

包专用:

class->顶级类可以是包专用的。它只能从同一个包访问。不是来自子包装,不是来自外包装。

实例变量->可从同一包访问。不是来自子包装,不是来自外包装。

受保护的:

class->无法保护顶级类。

实例变量->只能在同一包或子包中访问。扩展类时只能在包外部访问。

公众:

类->可从包/子包/另一个包访问

实例变量->可从包/子包/另一个包访问

下面是详细的答案

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

Java中的访问说明符:java中有4个访问说明符,即private、packageprivate(默认)、protected和public,访问顺序依次递增。

私人:当您正在开发某个类,并且希望该类的成员不暴露在该类之外时,应该将其声明为私有。私有成员只能在定义了它们的类(即封闭类)中访问。私有成员可以在“this”引用上访问,也可以在包含这些成员的类的其他实例上访问,但只能在该类的定义内访问。

包专用(默认):除了下面描述的访问之外,此访问说明符还将提供专用访问说明符指定的访问。

当您开发某个包并因此开发其中的某个类(比如Class1)时,您可以使用默认(无需明确提及)访问说明符,将类中的成员暴露给(同一)包中的其他类。在这些其他类(在同一个包中)中,您可以访问Class1实例上的这些默认成员。此外,您还可以在Class1的子类中访问这些默认成员,例如Class2(在该引用上、Class1的实例上或Class2的实例上)。

基本上,在同一个包中,您可以直接访问类实例上的默认成员,也可以访问子类中的“this”引用。

受保护的:除了下面描述的访问之外,此访问说明符还将提供由包专用访问说明符指定的访问。

当您正在开发某个包,从而在其中开发某个类(例如Class1)时,如果您不希望在包外部(例如在包的消费者的包中,即使用您的API的客户机)访问Class1中的数据成员,则应在Class1中使用受保护的访问说明符,但您希望创建一个例外,并且仅当客户端编写扩展Class1的Class2类时才允许访问该成员。因此,一般来说,受保护的成员可以在派生类(即Class2)中的“this”引用上访问,也可以在Class2的显式实例上访问。

请注意:

您将无法访问中继承的Class1受保护成员如果您试图在Class1的显式实例上访问它,尽管它是遗传的。当您在相同/不同的包中编写另一个类Class3时如果扩展了Class2,则可以访问Class1中的受保护成员该引用以及Class3的显式实例。这将对于任何扩展的层次结构(即受保护的成员)均为true仍然可以在此引用或扩展实例上访问班注意,在Class3中,如果创建Class2的实例但您将无法从Class1访问受保护的成员它是遗传的。

所以,底线是,只有当来自此其他包的某个类、包含此受保护成员的扩展类以及受保护成员在扩展类的定义内通过“this”引用或扩展类的显式实例访问时,才能在其他包中访问受保护成员。

public:除了下面描述的访问之外,此访问说明符还将提供受保护访问说明符指定的访问。

当您正在开发某个包以及其中的某个类(比如Class1)时,如果您希望在其他包的某个类别中创建的Class1实例的其他包中可以访问Class1中的数据成员,则应使用Class1中数据成员的公共访问说明符。基本上,当您打算无条件地向世界公开数据成员时,应该使用此访问说明符。

____________________________________________________________________
                | 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         |       ✔       |     ✘     |       ✘       |   ✘    
____________________________________________________________________

私有的

方法、变量和构造函数

声明为私有的方法、变量和构造函数只能在声明的类本身内访问。

类和接口

专用访问修饰符是限制性最强的访问级别。类和接口不能是私有的。

Note

如果类中存在公共getter方法,则可以在类外部访问声明为私有的变量。在超类中声明为受保护的变量、方法和构造函数只能由其他包中的子类或受保护成员类的包中的任何类访问。

受保护的

类和接口

受保护的访问修饰符不能应用于类和接口。

方法、字段可以声明为受保护,但接口中的方法和字段不能声明为受。

Note

受保护的访问使子类有机会使用helper方法或变量,同时防止非相关类尝试使用它。

平民的

声明为公共的类、方法、构造函数、接口等可以从任何其他类访问。

因此,可以从属于Java Universe的任何类访问在公共类中声明的字段、方法和块。

不同的软件包

但是,如果我们试图访问的公共类位于不同的包中,那么仍然需要导入公共类。

由于类继承,类的所有公共方法和变量都由其子类继承。

默认-无关键字:

默认访问修饰符意味着我们不为类、字段、方法等显式声明访问修饰符。

在相同的软件包中

没有任何访问控制修饰符的变量或方法可用于同一包中的任何其他类。接口中的字段是隐式的公共静态final,接口中的方法默认是公共的。

Note

我们无法覆盖静态字段。如果尝试覆盖,则不会显示任何错误但除了我们之外,它不起作用。

相关答案

重写java中的静态方法

参考链接

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.htmlhttp://www.tutorialspoint.com/java/java_access_modifiers.htm