0
votes

I have read a sentence here like below

A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the super class.

Now I have a code like below

class Locker {

private String secret = "This is my secret";

public class Util { }

}

class StealSecret extends Locker.Util { }

But I am getting an compile time error like below

No enclosing instance of type Locker is available due to some intermediate constructor invocation

I am unable to understand what exactly is causing the compile time error. Is it that what I read in the link is wrong ?

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

2
Declare Util class as static. You get this error because the inner class can only exist when an instance of outer class exists. Since you did not instantiate the outer class, inner class won't be available. But thats gonna bring you to whole another story with your testing....Jaskaranbir Singh
then why it is not mentioned in the oracle docs ? It is never told in the docs to make the class static. The code is as per the statement in the oracle docs. Do you think that the code is not inline with the statement ?Dilip Kumar
Not really inherent to static nested classes, look at this: stackoverflow.com/questions/17706978/…guido
@DilipKumar because it's irrelevant. The article is not about how to declare and instantiate nested classes. It's about accessibility of outer class members to nested classes. If you read an article saying "this car can go up to 200 km/hour", would you complain that it doesn't explain that to start the car, you need to turn the key?JB Nizet

2 Answers

3
votes

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();
    }
}
1
votes

Let's start with the quotation you are analyzing:

A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the super class.

In the sentence above, the enclosing class is your Locker, the nested class is Locker.Util and the private field is secret. For a subclass to inherit the nested class, it means that you need to extend the enclosing class, not the nested class:

class StealSecret extends Locker {
    public StealSecret() {
        StealSecret.Util u = new StealSecret.Util();
        System.out.println(u.getSecret());
    }   
}

in this case, the inherited nested class instance would have indirect access to the private enclosing class field secret:

class Util { 
    String getSecret() { return secret; } 
}  

In here you can see how the inherited nested class will access the private field for the enclosing class: https://ideone.com/NK9Brs

The compile error you get:

No enclosing instance of type Locker is available due to some intermediate constructor invocation

is a by-product of your mistake of having StealSecret try to extend Locker.Util outside of the Locker classand that is because a non-static nested class cannot exists without an instance of its enclosing class.