如何解决超类的私有方法?

时间:2015-06-03 01:31:55

标签: java

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 的私人方法”。

5 个答案:

答案 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)是一种不同的方法。