Java中受保护和包私有访问修饰符之间的区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18494938/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
difference between protected and package-private access modifiers in Java?
提问by eagertoLearn
I have seen various articles on differences between the protected and package private modifiers. One thing I found contradictory between these two posts
我看过很多关于 protected 和 package private 修饰符之间差异的文章。我发现这两篇文章之间存在矛盾的一件事
Isn't "package private" member access synonymous with the default (no-modifier) access?
In this the accepted answer says that
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
Why the protected modifier behave differently here in Java subclass?
In this the accepted answer says that
To satisfy protected level access two conditions must be met:
- The classes must be in the same package.
- There must be an inheritance relationship.
在这个接受的答案说
protected 修饰符指定该成员只能在它自己的包中访问(如包私有),此外,它的类的子类在另一个包中可以访问。
在这个接受的答案说
要满足受保护级别的访问,必须满足两个条件:
- 这些类必须在同一个包中。
- 必须有继承关系。
Aren't they contradictory? from my understanding of other articles, the first post gives the correct answer that protected == package-private + subclass in other package.
他们不矛盾吗?根据我对其他文章的理解,第一篇文章给出的正确答案是protected == package-private + subclass in other package。
If this statement is correct, then why this code fails with the following error message on my subclass Cat on line 17
如果此语句是正确的,那么为什么此代码失败并在第 17 行的子类 Cat 上显示以下错误消息
The method testInstanceMethod() from the type Animal is not visible
my code for super and subclass are below.
我的超级和子类代码如下。
package inheritance;
public class Animal {
public static void testClassMethod() {
System.out.println("The class" + " method in Animal.");
}
protected void testInstanceMethod() {
System.out.println("The instance " + " method in Animal.");
}
}
package testpackage;
import inheritance.Animal;
public class Cat extends Animal{
public static void testClassMethod() {
System.out.println("The class method" + " in Cat.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Cat.");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
myAnimal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
Please clarify why the above code fails. That would be very useful. Thanks
请说明上述代码失败的原因。那将非常有用。谢谢
采纳答案by axtavt
The first answer is basically correct - protected
members can be accessed by
第一个答案基本上是正确的 -protected
成员可以通过
- classes from the same package
- subclasses of the declaring class from other packages
- 来自同一个包的类
- 来自其他包的声明类的子类
However, there is a little trick:
但是,有一个小技巧:
6.6.2 Details on protected Access
A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.
6.6.2 受保护访问的详细信息
对象的受保护成员或构造函数可以从包外部访问,在该包中仅由负责实现该对象的代码声明它。
It means that subclass from other package cannot access protected
members of arbitrary instances of their superclasses, they can only access them on instances of their own type (where type is a compile-time type of expression, since it's a compile-time check).
这意味着来自其他包的子类不能访问protected
其超类的任意实例的成员,它们只能在自己类型的实例上访问它们(其中 type 是编译时表达式类型,因为它是编译时检查)。
For example (assuming that this code is in Cat
):
例如(假设此代码在 中Cat
):
Dog dog = new Dog();
Animal cat = new Cat();
dog.testInstanceMethod(); // Not allowed, because Cat should not be able to access protected members of Dog
cat.testInstanceMethod(); // Not allowed, because compiler doesn't know that runtime type of cat is Cat
((Cat) cat).testInstanceMethod(); // Allowed
It makes sense, because accessing of protected
members of Dog
by Cat
may break invariants of Dog
, whereas Cat
can access its own protected
members safely, because it knows how to ensure its own invariants.
这是有道理的,因为访问by的protected
成员可能会破坏 的不变量,而可以安全地访问自己的成员,因为它知道如何确保自己的不变量。Dog
Cat
Dog
Cat
protected
Detailed rules:
详细规则:
6.6.2.1 Access to a protected Member
Let C be the class in which a protected member m is declared. Access is permitted only within the body of a subclass S of C. In addition, if Id denotes an instance field or instance method, then:
- If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.
- If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.
6.6.2.2 Qualified Access to a protected Constructor
Let C be the class in which a protected constructor is declared and let S be the innermost class in whose declaration the use of the protected constructor occurs. Then:
- If the access is by a superclass constructor invocation super(. . .) or by a qualified superclass constructor invocation of the form E.super(. . .), where E is a Primary expression, then the access is permitted.
- If the access is by an anonymous class instance creation expression of the form new C(. . .){...} or by a qualified class instance creation expression of the form E.new C(. . .){...}, where E is a Primary expression, then the access is permitted.
- Otherwise, if the access is by a simple class instance creation expression of the form new C(. . .) or by a qualified class instance creation expression of the form E.new C(. . .), where E is a Primary expression, then the access is not permitted. A protected constructor can be accessed by a class instance creation expression (that does not declare an anonymous class) only from within the package in which it is defined.
6.6.2.1 访问受保护成员
设 C 是声明受保护成员 m 的类。仅允许在 C 的子类 S 的主体内访问。此外,如果 Id 表示实例字段或实例方法,则:
- 如果访问是通过限定名称 Q.Id 进行的,其中 Q 是 ExpressionName,那么当且仅当表达式 Q 的类型是 S 或 S 的子类时才允许访问。
- 如果访问是通过字段访问表达式 E.Id(其中 E 是主表达式)或通过方法调用表达式 E.Id(. . .)(其中 E 是主表达式),则允许访问当且仅当如果 E 的类型是 S 或 S 的子类。
6.6.2.2 对受保护构造函数的限定访问
设 C 为声明受保护构造函数的类,设 S 为声明中使用受保护构造函数的最内层类。然后:
- 如果访问是通过超类构造函数调用 super(. . .) 或通过 E.super(. . .) 形式的限定超类构造函数调用进行的,其中 E 是主表达式,则允许访问。
- 如果访问是通过 new C(. . .){...} 形式的匿名类实例创建表达式或通过 E.new C(. . .){... },其中 E 是 Primary 表达式,则允许访问。
- 否则,如果访问是通过 new C(. . .) 形式的简单类实例创建表达式或通过 E.new C(. . .) 形式的限定类实例创建表达式进行的,其中 E 是主表达式,则不允许访问。类实例创建表达式(不声明匿名类)只能从定义它的包中访问受保护的构造函数。
See also:
也可以看看:
回答by Arun
You have created an Cat instance and cast it to its super class type i.e. Animal type. As per Animal type its testInstanceMethod is visible in same package or any subtypes. If you didn't cast to Animal type the code will compile.
您已经创建了一个 Cat 实例并将其转换为它的超类类型,即 Animal 类型。根据 Animal 类型,其 testInstanceMethod 在同一包或任何子类型中可见。如果您没有转换为 Animal 类型,代码将被编译。
Hope that helps
希望有帮助
./Arun
./阿伦
回答by Muhammad kazmi
In protected access the members are accessed in the same package and for inherited class member in another package can also be accessed.
在受保护的访问中,成员在同一个包中被访问,对于另一个包中的继承类成员,也可以被访问。
In package access the members of the classes in the same package can be accessed. Class members in other packages can't be accessed in package access.
在包访问中,可以访问同一包中的类的成员。在包访问中无法访问其他包中的类成员。