Nested Class' Access to Enclosing Class' Private Data Members

Nested class' access to enclosing class' private data members

Member x and y are non-static data member of Enclosing, which means that they only exist within a concrete object of Enclosing class. Without a concrete object, neither x nor y exist. Meanwhile, you are trying to refer to x and y without an object. That can't be done, which is what the compiler is trying to tell you.

If you want to initialize members Inner::foo and Inner::bar from x and y, you have to pass a concrete object of Enclosing type into the Inners constructor. For example

class Enclosing::Inner {    
explicit Inner(const Enclosing& e) : foo(e.x), bar(e.y)
{}
//...
};

Extra note: in the original C++98 the inner class has no special privileges is accessing the outer class. With C++98 compiler you'd either have to give the inner class the necessary privileges (friendship) or expose the members x and y as public. However, this situation was classified as a defect in C++98, and it was decided that inner classes should have full access to outer class members (even private ones). So, whether you have to do anything extra with regard to access privileges depends on your compiler.

How do inner class access enclosing class' private members in higher versions of Java?

The only thing that stops a class from accessing another class’s private members, is the JVM (or precisely its verifier) rejecting the access. So all it needs to make it possible, is the collaboration of the JVM to allow it.

While Java 1.1 introduced inner classes in a way that did not require changes to the JVM, the JVM has gone through so many changes in the meanwhile, that it is rather surprising that it took until Java 11 to change that.

Java 11 introduced the NestHost and NestMembers bytecode attributes to allow class files to denote that they belong to a so called “nest”. All classes belonging to the same nest are allowed to access each others private members. As said, the only thing that needed to be changed, is the JVM’s verifier to allow such access. And, of course, the compiler to utilize this feature. See also JEP 181.

So you could say that the JVM still doesn’t know anything about inner classes, because which classes belong to a nest, is decided by whichever tool generated the class files (e.g. the Java source code compiler). So it is possible to produce class files with other tools using nests without following the inner class semantic.

For completion, it should be mentioned that class files do also contain the information about inner class relationships, using the InnerClasses attribute. But this is only used by compilers and Reflection, whereas the JVM doesn’t use this information when deciding whether an access is legal or not.

Can enclosing class access nested class?

Can enclosing class access nested class?

Yes, if the enclosing class have an instance (an object) of the nested class.

A class is a class is a class... Nesting doesn't matter, you must always have an instance of the class to be able to call a (non-static) member function.

Subclass of a public nested class is unable to access private members of enclosing class

The other answers have explained the reason for the exception, but have not addressed

Please give me an example explaining the way to access the private
members of enclosing class by extending the inner class

The quote from your document states

A nested class has access to all the private members of its enclosing
class—both fields and methods.

A nested class is a class that is declared within another. Locker.Util is a nested class. StealSecret is not (even if it did compile, see below for a trick to do that).

If you really need to extend that inner class and have access to the private members of the Locker class, you'll need to declare the subclass within Locker as well

For example,

public class Locker {
private String secret = "This is my secret";

public class Util {
}

public class StealSecret extends Locker.Util {
public StealSecret() {
System.out.println(secret); // access
}
}
}

The StealSecret class extends an inner class, which requires a reference to an instance of that inner class' enclosing class. You can use this trick to provide that reference

class StealSecret extends Locker.Util {
public StealSecret(Locker enclosing) {
enclosing.super();
}
}

Nested class member access on C++11

To close this question I'll take this as an answer:

"No, it's not treated as a member of the class, it's just scoped inside of it like anything else. You'll need an instance of Enclosing to access it's members."

  • this and several other comments addresses the problem in my code. Basically this is something that remains true for C++11.

In Java nested classes, can the enclosing class access private members of inner classes?

Yes, that's fine. From the JLS, section 6.6.1:

Otherwise, if the member or constructor is declared private, then 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.

You can even refer to a private member of nested type X within another nested type Y so long as they share a top-level class.

At the bytecode level, I believe this is all implemented by adding synthetic package-access methods.



Related Topics



Leave a reply



Submit