class A{
private void sayA(){
System.out.println(\"Private method of A\");
}
public static void main(String args[]){
A instanceA=new B();
ins
Accessibility is a compile time concept (reflected in Reflection APIs).
From the Java Language Specification
Note that accessibility is a static property that can be determined at compile time; it depends only on types and declaration modifiers.
That is, the compiler doesn't care what the runtime type of the instance referenced by your variable named instanceA
will be
A instanceA = new B();
It only cares that you invoked a method on a reference of static type A
. That method is private
and since you are within the body of the class which declares it, it is visible, and therefore usable.
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
For spiderman in comments, 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();
}
}
InstanceA is the instance of A actually, so it can call the functions of A, but if the function is private, means that only the class declares 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.
}
}
It's because you're assigning B to A, so the resulting instance has access to the methods of A.
If you change to B instanceA=new B()
, the subsequent line will not compile (which I believe is what 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{
}
private
means that only the class that declares the field can see it. Because you're calling instanceA.sayA();
from within class A
the method is visible and the code both compiles and runs. If you were to try to call that method from within class B
or any other class you would get the compile warning that The method sayA() from the type A is not visible
Only virtual methods are really parts of the class instance - you can imagine all the other methods as simply being a static method that take an argument called this
.
So when you rewrite the code to show this more explicitly (note that I'm using C#, Java is a bit different but the same principle mostly 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 doesn't really tie in to the instance of the type, only to the type itself. So no matter whether you call new B().sayA()
or new A().sayA()
, the same method is called, just with a different argument.
On the other hand, if you're writing code from inside of B
, the sayA
method simply isn't accessible - again, A.sayA(...)
is obviously inaccessible, since it's private to A
.
This changes when you make the method public or protected, and virtual (default in Java). In that case, the actual method that's called depends on the runtime type you're calling the method on, not the compile-time type, nor the scope you call it from. This means that new B().VirtualA()
will call the same method as ((A)new B()).VirtualA()
, even though the compile-time types are different. And of course new A().VirtualA()
may (or may not - depending on whether B
overrides VirtualA
) be a different method.