尝试在位于其他包的子类中使用受保护的构造函数时,Eclipse显示错误
Hello Stackoverflow社区: – ]
我是新成员,首先我要感谢您提供的非常有用的建议和更正。 因为我是法国人,如果我的英语不完美,请原谅我。
这是我的问题:我正在学习Java编程语言,我想测试一些inheritance的东西。 如果我理解正确,声明为protected
的字段可以由与声明受保护字段的类位于同一个包中的类以及它的所有子类访问,无论它们是否在同一个包中。
所以,我做了这4个类来测试这个。 我有一个名为“package1”的包,包含类A和C.我还有一个名为“package 2”的包,其中包含类A2和C,其中A2扩展为A.两个C类具有完全相同的代码,只是包中的它们位于变化。它们不会延伸A.
在A类中,我声明了一些具有不同访问属性的成员,尤其是使用protected
visibility声明的构造函数。 这是四个类的代码。
package1,A类:
package package1; public class A { public int a; protected int b; private int c; int d; protected static int h = 30; protected void aff(){ System.out.println(h); } protected A(){ a = 1; b = 2; c = 3; d = 4; } public static void main(String[] args) { // TODO Auto-generated method stub } }
包1,C类:
package package1; public class C { public C(){ super(); } public void app(){ A obj = new A(); //////// OK } public static void main(String[] args) { // TODO Auto-generated method stub A obj = new A(); //////// OK obj.aff(); //////// OK System.out.println(obj.a); } }
package2,A2类(扩展A):
package package2; import package1.A; public class A2 extends A{ public int x; A2(){ super(); } public void app(){ A obj = new A(); //////// ERROR } public static void main(String[] args) { // TODO Auto-generated method stub A obj = new A(); //////// ERROR A2 obj2 = new A2(); obj2.aff(); //////// OK } }
package2,C类:
package package2; import package1.A; public class C { public C(){ super(); } public void app(){ A obj = new A(); //////// ERROR } public static void main(String[] args) { // TODO Auto-generated method stub A obj = new A(); //////// ERROR obj.aff(); //////// ERROR System.out.println(obj.a); } }
对于package2中的C类,代码A obj = new A();
抛出错误但是package1中的C类不是这样。 这是正确的,因为构造函数被声明为protected
,而package2中的C不是A的子类,而C在package1中。 到那时,我理解。
我遇到问题的地方是代码A obj = new A();
在A2类中:无论在何处编写,它都会抛出错误The constructor A() is not visible
……由于类A构造函数被声明为protected
,为什么我不能在A2类中实例化类型A的对象?
当我将A构造函数声明为public
,它可以正常工作。 此外,如果我通过让代码原样将A2类放在package1中,它也可以工作。 似乎只有当A类构造函数声明为protected
子类位于同一个包中时才能在A的子类中实例化A对象。
但是,正如您所看到的,如果我首先实例化一个A2对象,然后调用类A protected
aff()方法,那么它就可以工作并且遵守受保护的规则。
有人对此错误有解释吗? 当在其子类中实例化超类的对象时,如果超类构造函数被声明为protected
,则此子类是否始终与其超类位于同一个包中? 为什么会这样呢?
或者这是否必须处理构造函数不是由子类inheritance的事实? 但我无法弄清楚为什么如果是这样的……
非常感谢您花时间阅读和回答: – ]
这很有趣,所以让我试着总结一下。 见JLS#6.6.1
protected
可以限定构造函数或类的成员。
“member”包括字段/方法(静态/实例),嵌套类/接口(静态/内部)
class A { protected int f protected void m(){} protected class X{} protected interface Y{}
首先,要访问受保护的构造函数/成员,必须可以访问封闭类(例如A
)。 假设是这样的话,那么 –
– 在包裹内 –
受保护的构造函数或成员可以在同一个包中的任何位置访问。
– 包裹外 –
受保护的构造函数只能在子类构造函数中访问,可以作为super()
调用,也可以作为匿名类实例化。
受保护的静态字段/方法,嵌套类/接口可在子类主体内的任何位置访问。
受保护的实例字段/方法更复杂 –
- 受保护的“m”在A类中定义
-
obj.m
在B类(A的包外)访问 -
obj
的类型是C.
仅当B是A的子类,并且C是B的子类或C是B时,才授予访问obj.m
总是允许super.m
; 但是,目前尚不清楚JLS是如何构建问题的。 似乎访问应该与this.m
相同,因此允许访问。
请参阅Java语言规范 :
受保护的成员或对象的构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。
A2
类不对 new A()
调用中A
的实现负责。
意思是,它不负责A
实例的实现,但它负责实现A2
的实例。