我在派生类中创建基类的实例,并尝试访问受保护的成员。
我可以直接访问派生类中的受保护成员,而无需实例化基类。
基类:
package com.core;
public class MyCollection {
protected Integer intg;
}
同一包中的派生类-
package com.core;
public class MyCollection3 extends MyCollection {
public void test(){
MyCollection mc = new MyCollection();
mc.intg=1; // Works
}
}
不同包中的派生类-
package secondary;
import com.core.MyCollection;
public class MyCollection2 extends MyCollection{
public void test(){
MyCollection mc = new MyCollection();
mc.intg = 1; //!!! compile time error - change visibility of"intg" to protected
}
}
当派生类也位于同一包中但派生类位于不同包中时,如何使用基类的实例访问派生类中基类的受保护成员呢?
如果我将受保护的成员标记为"静态",则可以使用驻留在不同包中的派生类中的基类实例来访问基类的受保护成员。
Java受保护的访问的可能重复项不起作用---其实多数民众赞成错了! 抱歉! 这绝对是骗子。
不用担心,您的IDE不会对这个问题产生任何影响,因为这与Java语言本身的语义有关。
为什么我什至不能说我扩展了该类,为什么我却不能访问受保护的Java方法?
没错,您是对的。之所以不能访问该字段,是因为您与该类不在同一个程序包中,也没有访问同一个类的继承成员。
最后一点很关键-如果您写过
MyCollection2 mc = new MyCollection2();
mc.intg = 1;
那么这将起作用,因为您正在更改自己类的受保护成员(该类通过继承出现在该类中)。但是,在您的情况下,您尝试在不同的程序包中更改其他类的受保护成员。因此,拒绝访问就不足为奇了。
这种解释确实很容易理解。 我看了一下Java语言规范,对它们的详细说明让我大吃一惊!!!
@Tarun-如果答案对您有用,请将其标记为已接受(在投票计数器下方打勾)
我不知道这个功能。 我现在将其标记为已回答。
@Doyle我认为这个答案确实有道理,但是您可能会忽略为什么如果我们在MyCollection中将intg设为静态,为什么我们可以访问mc.intg
如果类成员是protected,则有2种情况:
If subclass is in same package
If subclass is in different package
I. Same package :
- Can access through inheritance
- Can access by creating an instance of parent class
II. Different package :
- Can only access through inheritance
有关所有用例,请参见下表:
Java教程说:
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.
在这种情况下,您正在访问另一个对象中的变量。碰巧的是,它具有与当前类相同的类,但是可见性检查不会对此进行检查。
因此,第二次您被拒绝访问,因为您位于不同的程序包中,而第一次您被授予访问权限是因为您在同一程序包中(而不是因为它是子类)
"第一次给您访问权限是因为您在同一个包中(而不是因为它是其子类)",这使我很清楚。 谢谢。
简而言之,这实际上是不可能的。似乎您应该重新考虑您的设计。
但是,如果您确定那是您想做的话,可以采取解决方法。您可以向MyCollection添加一个受保护的方法,该方法采用一个实例并代表您设置intg的值:
package com.core;
public class MyCollection {
protected Integer intg;
protected void setIntg(MyCollection collection, Integer newIntg) {
collection.intg = newIntg;
}
}
现在,您的子类可以访问此方法:
package secondary;
import com.core.MyCollection;
public class MyCollection2 extends MyCollection{
public void test(){
MyCollection mc = new MyCollection();
setIntg(mc, 1);
}
}
但是请注意,这是一种非常奇怪的方式。我再次建议您在重新设计之前必须重新考虑您的设计。
我明白你的意思。 对我而言,最简单的方法是直接实例化受保护的成员,而不是实例化基类并在其他程序包中进行访问。 我在玩Java时"错误地"做到了(不是我不是说我曾经是一个manaul测试人员:-)),然后我的开发人员都没有一个可以提供我可以想象的答案。 所以我在这里贴了
如果使用类MyCollection的新对象访问派生类(位于不同的程序包中),则不能访问受保护的变量。
您可以只写intg = 1;直接不做(new MyCollection)
像这样:
package secondary;
import com.core.MyCollection;
public class MyCollection2 extends MyCollection{
public void test(){
intg = 1;
}
}
根据Java的成员可访问性规则,如果不扩展类,则无法访问类的受保护成员。
您可以尝试以下方法。
package secondary;
import com.core.MyCollection;
public class MyCollection2 extends MyCollection{
public void test(){
intg = 1;
}
}
而不是创建新实例,请尝试分配值。会的。
同意你的推理