【发布时间】:2012-04-09 17:04:45
【问题描述】:
我正在尝试学习 java,但当我查看访问说明符时,我有一个疑问。如果没有指定默认值和java中受保护的访问说明符有什么区别?
【问题讨论】:
-
差异在this table 中清晰可见。
标签: java access-specifier
我正在尝试学习 java,但当我查看访问说明符时,我有一个疑问。如果没有指定默认值和java中受保护的访问说明符有什么区别?
【问题讨论】:
标签: java access-specifier
这个 Java tutorial 可能对你有用。
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
【讨论】:
protected 说明符允许相关类的所有子类(无论它们驻留在哪个包中)以及同一包中的其他代码访问。默认说明符允许同一包中的其他代码访问,但不允许位于不同包中的子类中的代码访问。见Java Language Specification Section 6.6。
编辑:根据 Michael Schmeißer 的要求(因此其他人不必通读 cmets 或点击链接即可找到此内容):接口的所有成员都是隐式公开的。实际上,为public 以外的接口成员指定任何访问说明符是编译时错误(尽管没有访问说明符默认为公共访问)。以下是 JLS 中针对类成员的完整规则集(有关包、顶级类和接口以及数组的规则,请参见上面的链接):
只有当类型是可访问的并且成员或构造函数声明为允许访问:
如果成员或构造函数声明为公共,则允许访问。
接口的所有成员都是隐式公开的。
否则,如果成员或构造函数被声明为受保护,则仅当满足以下条件之一时才允许访问:
对成员或构造函数的访问发生在包含声明受保护成员或构造函数的类的包内。
访问正确,如§6.6.2 中所述。 (此条款指的是允许派生类访问超类的受保护成员的规则;第 6.6.2 节开始:“对象的受保护成员或构造函数只能从声明它的包外部访问负责实现该对象的代码。” 然后详细说明。)
否则,如果成员或构造函数声明为私有,则当且仅当它出现在包含成员或构造函数声明的顶级类 (§7.6) 的主体内时,才允许访问。
否则,我们说有默认访问,只有当访问发生在声明类型的包内时才被允许。
【讨论】:
如果一个类的受保护数据成员、受保护方法位于同一个包中
使用继承
意味着我们可以通过继承该类来使用该类的受保护数据。
默认将访问限制在包级别,即使扩展了具有默认数据成员的类,我们也无法访问。
要检查它在 ProvideProtected 中 int x 的默认删除受保护关键字,将产生编译时错误。
1. SuperClass
package nee.superclass;
public class ProvideProtected {
protected int x=800;
}
2.Subclass
package nee.subclass;
import nee.superclass.*;
public class AccessProtected extends ProvideProtected
{
public void accessProtected()
{
System.out.println(x);
}
public static void main(String[] args) {
AccessProtected obj=new AccessProtected();
obj.accessProtected();
}
}
【讨论】:
受保护的访问修饰符:- 任何标记为受保护的东西在同一个包中可见,在子类中也可见。
默认访问:- 默认不是关键字。它适用于未指定访问修饰符的情况。它基本上是一个包级别修饰符。任何具有这种访问权限的东西都可以在同一个包中看到。
现在可以借助示例更好地解释差异
包 p1
public class A
{
protected void fn()
{
}
}
包 p1
public class B
{
A a1 = new A();
a1.fn();// fn() is visible inside the same package
}
}
现在我们来到不同包中的子类
包 p2
public class D extends A
{
void test()
{
A a1 = new new A();
//a1.fn() --> would give compilation error
fn();
super.fn();
}
}
fn(), super.fn() 不会报错。
所以,区别在于子类中的方法不能通过超类的引用来调用。要么你可以直接调用它,要么使用super。
注意super.fn() 必须是非静态方法的一部分。
【讨论】:
长话短说:
default 成员可用于同一包的所有其他类;
protected 成员在同一包的所有其他类和任何其他包的任何其他类中都可用,只要该类扩展了包含受保护成员的类即可。
【讨论】:
例子:
package p1;
protected class Parent{
}
import p1.*;
class Child extends Parent{}
【讨论】: