java package 修饰符_Java中的protected和package-private访问修饰符之间的区别?

本问题已经有最佳答案,请猛点这里访问。

我已经看到了关于受保护修饰符和包私有修饰符之间差异的各种文章。我发现这两个职位之间有一点矛盾

"package private"成员访问是否与默认(无修饰符)访问同义?

在这个问题上,公认的答案是

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.

为什么受保护的修饰符在Java子类中有不同的行为?

在这个问题上,公认的答案是

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==package private+other package中的子类。

如果此语句正确,那么为什么此代码会失败,并在第17行的子类cat上显示以下错误消息

The method testInstanceMethod() from the type Animal is not visible

我的super和subclass代码如下。

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();

}

}

请澄清上述代码失败的原因。那将是非常有用的。谢谢

您必须是一个cat才能使用testinstancemethod()。对动物的强制转换限制了对包lavel的访问,并且由于您的主程序位于不同的包中,所以代码失败。(我认为它甚至不会编译)。是的,该方法存在,但您没有权限访问它,因为它是由受保护动物声明的。

第二个声明应该被表述为:"为了满足受保护级别的访问,必须满足两个条件中的一个……"(另请参见我在该答案下面的评论。)

第一个答案基本上是正确的-可以通过访问protected成员

来自同一包的类

从其他包声明类的子类

但是,有一个小技巧:

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.

这意味着来自其他包的子类不能访问它们的超类的任意实例的protected成员,它们只能在自己类型的实例上访问它们(其中类型是编译时表达式类型,因为它是编译时检查)。

例如(假设此代码在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

这是有意义的,因为通过Cat访问Dog的protected成员可能破坏Dog的不变量,而Cat可以安全访问自己的protected成员,因为它知道如何确保自己的不变量。

细则:

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.

参见:

Java语言规范

我想我明白了,但还是需要一些时间来消化和理解。重写时,是否必须维护方法签名(包括访问修饰符签名)?似乎,如果一个超类有protected void get(){}和一个覆盖它的子类,它就不能有void get(){}的默认访问权。但它可以有public void get(){}或protected void get(){}。

@渴望学习-子类背后的思想总是可以使方法更容易访问,但不容易访问;这样,子类仍然符合超级类契约。换句话说,强制转换到超级类永远不应该给你更多的方法。

在受保护的访问中,成员可以在同一个包中访问,对于继承的类成员,也可以在另一个包中访问。

在包访问中,可以访问同一包中类的成员。在包访问中无法访问其他包中的类成员。

这个问题已经三岁多了,答案已经被接受了。你的回答也不会给已经被接受的答案增加任何有价值的东西,所以我不认为你的回答有什么意义(没有冒犯)。

阅读"公认的答案"让我大失所望……我不是一个语言语法律师(也不在电视上播放),所以我真的很欣赏这个"更简洁"的答案。

您已经创建了一个cat实例并将其强制转换为超级类类型,即动物类型。根据动物类型,它的TestInstanceMethod在同一个包或任何子类型中都可见。如果您没有强制转换为动物类型,代码将编译。

希望有所帮助

/阿伦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值