How is a private superclass method allowed?

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{ } 

I expected it to throw an exception at runtime, because at compile time the compiler checks if sayA() be called by reference A , and at runtime it checks whether sayA() call object B But instead, he printed Private Method A.

+6
source share
5 answers

Availability is a concept of compilation time (reflected in the Reflection API).

From the Java language specification

Note that accessibility is a static property that can be determined at compile time; it depends only on the types and modifiers of the declaration.

That is, the compiler doesn't care what type of instance of the instance your variable referenced by instanceA refers to will be

 A instanceA = new B(); 

Note that you called the method by reference of a static type A This method is private , and since you are inside the body of the class that declares it, it is visible and therefore can be used.

Otherwise, the member or constructor is declared private, and access is allowed if and only if it occurs in the upper level body of the class (ยง7.6), which includes the declaration of the member or constructor.


In the comments for Spider-Man, consider the following

 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(); } } 
+14
source

private means that only the class declaring the field can see it. Since you are calling instanceA.sayA(); from class A , the method is visible and the code compiles and runs. If you try to call this method from class B or any other class, you will get a compilation warning that The method sayA() from the type A is not visible

+12
source

This is because you assign B to A, so the resulting instance has access to methods A.

If you change to B instanceA=new B() , the next line will not compile (what do I think you expected?).

 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{ } 
+5
source

InstanceA is actually an instance of A, so it can call functions of A, but if the function is private, it means that only the class declares that the field can see it. eg:

 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. } } 
+1
source

Only virtual methods - these are really parts of the class instance - you can imagine that all the other methods are simply a static method that takes this argument.

So, when you rewrite the code to show this more explicitly (note that I am using C #, Java is a little different, but basically the same principle applies):

 class A { private static void sayA(A @this) { "Hi from A".Dump(); } public static void Test() { sayA(new B()); } } class B : A { } 

This makes it much more obvious what the scope of the method is - it does not bind to the type instance only to the type itself. Therefore, regardless of whether you call new B().sayA() or new A().sayA() , the same method is called, only with a different argument.

On the other hand, if you write code from B , the sayA method sayA simply unavailable - again, A.sayA(...) clearly unavailable because it is closed to A

This changes when you make the method public or secure, and virtual (by default in Java). In this case, the method being called depends on the type of execution to which you are calling the method, and not on the type of compilation time or on the scope from which you are calling it. This means that new B().VirtualA() will call the same method as ((A)new B()).VirtualA() , even if the compile time types are different. And, of course, new A().VirtualA() may (or may not - depending on whether B redefines VirtualA ) another method.

0
source

Source: https://habr.com/ru/post/988422/


All Articles