class A{
private void sayA(){
System.out.println("Private method of A");
}
public static void main(String args[]){
A instanceA=new B();
instanceA.sayA();
}
}
class B extends A{
}
我希望它在编译时抛出运行时异常,编译器会检查sayA()
是否可以在A
的引用上调用,并且在运行时它会检查{是否{可以在sayA()
的对象上调用{1}}。但它改为打印“ A 的私人方法”。
答案 0 :(得分:14)
辅助功能是一个编译时概念(反映在Reflection API中)。
From the Java Language Specification
请注意,辅助功能是一个可以在其中确定的静态属性 编译时间;它仅取决于类型和声明修饰符。
也就是说,编译器不关心名为instanceA
的变量引用的实例的运行时类型是什么
A instanceA = new B();
它只关心你在静态类型A
的引用上调用了一个方法。该方法是private
,因为你在声明它的类的主体内,它是可见的,因此可用。
否则,成员或构造函数被声明为private和access 当且仅当它出现在顶层的主体内时才被允许 包含成员或的声明的类(第7.6节) 构造
对于评论中的蜘蛛侠,请考虑以下内容
class A {
private void privateMethod () {
System.out.println("private method");
}
public void publicMethod() {
privateMethod();
}
}
class B extends A {}
class Example {
public static void main(String[] args) {
new B().publicMethod();
}
}
答案 1 :(得分:12)
private
表示只有声明该字段的类才能看到它。因为您从类instanceA.sayA();
中调用A
,所以该方法是可见的,并且代码都会编译并运行。如果您尝试从类B
或任何其他类中调用该方法,则会收到The method sayA() from the type A is not visible
答案 2 :(得分:5)
这是因为您将B分配给A,因此生成的实例可以访问A的方法。
如果您更改为B instanceA=new B()
,后续行将无法编译(我相信您的预期是什么?)。
class A{
private void sayA(){
System.out.println("Private method of A");
}
public static void main(String args[]){
B instanceA=new B();
instanceA.sayA(); # This line won't compile/run.
}
}
class B extends A{
}
答案 3 :(得分:1)
InstanceA实际上是A的实例,所以它可以调用A的函数,但如果函数是私有的,则意味着只有类声明该字段才能看到它。 例如:
public class A
{
private void sayA(){
System.out.println("Private method of A");
}
public void funOfA(){
System.out.println("fun of A");
}
public static void main(String args[]){
A instanceA=new B();
instanceA.sayA();
instanceA.funOfA();
}
}
public class B extends A
{
public void funOfB()
{
System.out.println("fun of B");
}
public static void main(String args[]){
A instanceA=new B();
instanceA.funOfA();
// instanceA.sayA(); // This Line won't compile and run.
// instanceA.funOfB(); // This Line won't compile and run.
B instanceB = new B();
instanceB.funOfA();
instanceB.funOfB();
// instanceB.sayA(); // This Line won't compile and run.
}
}
答案 4 :(得分:0)
只有虚拟方法实际上是类实例的一部分 - 您可以将所有其他方法想象成一个静态方法,它接受一个名为this
的参数。
因此,当您重写代码以更明确地显示它时(注意我使用的是C#,Java有点不同,但同样的原则主要适用):
class A
{
private static void sayA(A @this)
{
"Hi from A".Dump();
}
public static void Test()
{
sayA(new B());
}
}
class B : A { }
这使得该方法的范围更加明显 - 它不会真正与该类型的实例绑定,而只与该类型本身相关联。因此,无论您是调用new B().sayA()
还是new A().sayA()
,都会调用相同的方法,只是使用不同的参数。
另一方面,如果您从B
内部编写代码,则sayA
方法无法访问 - 同样,A.sayA(...)
显然无法访问,因为它是私有的到A
。
当您将方法设置为public或protected,以及virtual(Java中的默认值)时,这会更改。在这种情况下,调用的实际方法取决于您调用方法的运行时类型,而不是编译时类型,也不是您调用它的范围。这意味着new B().VirtualA()
将调用与((A)new B()).VirtualA()
相同的方法,即使编译时类型不同。当然,new A().VirtualA()
可能(或可能不会 - 取决于B
是否覆盖VirtualA
)是一种不同的方法。