Just like the superclass constructor, setN
is perfectly accessible in Sub
. This is because, as your linked Q&A explained, private
members declared in an inner class are accessible everywhere as long as you are inside the top-level class. So the problem is somewhere else.
If you are using IntelliJ, the error message it gives is "setN
has private access...", which is more useful and lets you fix the error immediately (and setN
being private also plays a role as you will see). But javac
's error message, "cannot find symbol setN
", shows that this isn't actually about accessibility, and that the compiler can't actually find setN
.
According to the spec, a simple method name like setN
consists of a single UnqualifiedMethodIdentifier which specifies the name of the method to be invoked. The rules of method invocation require that the UnqualifiedMethodIdentifier denotes a method that is in scope at the point of the method invocation.
setN
is actually not in scope in the constructor of Sub
. The scope of setN
is only Super
. See also Scope of a Declaration in the spec.
But doesn't Sub
inherit setN
from Super
? Well, it doesn't. private
members are not inherited. See this section for the conditions for inheritance.
A class C inherits from its direct superclass type D all concrete
methods m (both static and instance) for which all of the following
are true:
m is a member of D.
m is public, protected, or declared with package access in the same
package as C.
No method declared in C has a signature that is a subsignature
(§8.4.2) of the signature of m as a member of D.
If you use another form (instead of a simple name) to refer to Super.setN
, like super.setN(5);
, or ((Super)this).setN(5);
then it can compile just fine.
For why these work, see the compile-time step 1 of processing a method call, where the compiler determines in which type it should search for a method declaration. If the type to search is Super
, then it would compile, because Super
actually has the setN
method, whereas Sub
does not inherit it from Super
, so does not have it as a member.
Note that constructor calls and method calls are treated completely separately by the language spec and they have completely different rules. The super();
syntax is essentially "hardcoded" into the language - there is no "scope" or "names" of a constructor or anything like that. The constructor just has to be accessible for you to call it.