为什么另一个包中的子类无法访问受保护的方法?

我在两个不同的包中有两个类:

package package1; public class Class1 { public void tryMePublic() { } protected void tryMeProtected() { } } package package2; import package1.Class1; public class Class2 extends Class1 { doNow() { Class1 c = new Class1(); c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1 tryMeProtected(); // No error } } 

我可以理解为什么调用tryMeProtected()没有错误,因为Class2看到这个方法,因为它inheritance自Class1

但是为什么Class2的对象不能使用c.tryMeProtected();Class1的对象上访问此方法c.tryMeProtected();

受保护的方法只能通过包外的子类中的inheritance访问 。 因此第二种方法tryMeProtected(); 作品。

下面的代码不会编译,因为我们没有调用受保护方法的inheritance版本。

  Class1 c = new Class1(); c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1 

请按照此stackoverflow链接进行更多说明。

我相信你误解了packageprotected可见性之间的区别。

 package package1; public class MyClass1 { public void tryMePublic() { System.out.println("I'm public"); } protected void tryMeProtected() { System.out.println("I'm protected"); } void tryMePackage() { System.out.println("I'm package"); } } 
  • 无论您身在何处,都可以访问tryMePublic
  • 每个子类和同一个包中的每个类都可以访问tryMeProtected
  • tryMePackage将在同一个包中的每个类都可访问(如果它们在不同的包中,则不在子类中可用)

儿童class在同一个包中

 package package1; public class Class2 extends MyClass1 { public void doNow() { tryMePublic(); // OK tryMeProtected(); // OK tryMePackage(); // OK } } 

儿童class在不同的包

 package package2; import package1.MyClass1; public class Class3 extends MyClass1 { public void doNow() { MyClass1 c = new MyClass1(); c.tryMeProtected() // ERROR, because only public methods are allowed to be called on class instance, whereever you are tryMePublic(); // OK tryMeProtected(); // OK tryMePackage(); // ERROR } } 

您使用两个不同的包,并且不通过直接inheritance访问父属性,而是通过子类中声明的中间父实例(类似于组合)访问。 =>那不是protected的方式。

只有直接inheritance才允许访问受保护的父级属性。

因此,你可以这样做:

 public class Class2 extends Class1 { doNow() { tryMeProtected(); // No error since direct inheritance } } 

但从来没有这样:

 public class Class2 extends Class1 { doNow() { Class1 c = new Class1(); c.tryMeProtected(); // this is not a direct inheritance! since `c`, although a parent one is an intermediate instance created in the child instance. => bad } } 

实际上,这是protected关键字的特殊性,经常被误解。

根据Java Protected Access修饰符定义在超类中声明受保护的方法只能由其他包中的子类或受保护成员类的包中的任何类访问。

您无法通过创建类的对象来访问受保护的方法。 因此,要访问Protected方法,您必须扩展超类。(这说明您的第二个调用是正确的)

它可以通过两种方式实现

1.通过创建Child类的对象然后访问Parent类的受保护方法。

套餐1

 public class Class1 { protected void m1() { System.out.println("m1 called"); } } 

包2

 public class Class2 extends Class1 { public static void main(String[] args) { Class2 class2 = new Class2(); class2.m1(); } } 

2.或者直接从Child类调用该方法

eg tryMeProtected();

首先,您需要了解两件事:

1)包’Y’中的类’X’的protected成员函数可以由子类访问,即扩展它的类(即使子类在包中而不是’Y’)。 这就是为什么,

 tryMeProtected(); // Showed no error because this was called by class 2 that is the subclass. 

2)如果包含在’Y’中的类’X’的protected成员函数,则它本身不能被访问。

[一个简单的比喻:一只鸟在窝1中保持着飞到巢中2.从巢2中,它无法进入巢1中保存的鸡蛋。]同样,一个类无法访问其成员函数(除非公开声明。)如果它在另一个包中。

这就是为什么 :

 c.tryMeProtected(); // Showed error because this was called by class 1 reference. // You can also think of it as class 1 cannot inherit itself.