Update:
I'm still a unclear about this. I'm trying to find the JLS to describe this behaviour. Instead, I found this quote in 8.3 of the JLS:
Member class declarations (§8.5) describe nested classes that are members of the surrounding class. Member classes may be static, in which case they have no access to the instance variables of the surrounding class; or they may be inner classes (§8.1.3).
Doesn't this mean the nested static class should not have access to the outer class variables? Where can I find clarification of what the behaviour should be?
End Update
I am seeking some clarification of the accesiblity of the private members of an outer class by an instance of a static nested class. The Java tutorials state:
a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience
The accepted answer from this question (Java inner class and static nested class) mentions:
The only real conceivable reason to create a static inner class is that such a class has access to its containing class's private static members
But it seems a static nested class also has access to the private members of any instance of the enclosing class? This would be behaviourly different from any other top level class. In the example below, the static nested class Builder
can access the private members of any instance of the Config
class. But another top level class would not be able to do this (e.g. an instance of ConfigTest
would not be able to change the private members of a config object as shown in the commented manipulateConfig
method.
Am I understanding this correctly? I haven't found a reference in the JLS to clarify this for me.
Config:
public class Config {
private String param1;
private int param2;
private Config() {}
public String getParam1() { return param1; }
public int getParam2() { return param2; }
@Override
public String toString() {
return "Config{" + "param1=" + param1 + ", param2=" + param2 + '}';
}
public static class Builder {
private String param1;
private int param2;
public Builder setParam1(String param1) { this.param1 = param1; return this; }
public Builder setParam2(int param2) { this.param2 = param2; return this; }
public Config build() {
Config config = new Config();
config.param1 = param1; // <- Accessing private member of outer class
config.param2 = param2;
return config;
}
public void modifyParm2(Config config, int newVal) {
config.param2 = newVal; // <- Able to modify private member of any enclosing class
}
}
}
ConfigTest:
public class ConfigTest {
private Config getConfig() {
Config.Builder builder = new Config.Builder();
Config config = builder
.setParam1("Val1")
.setParam2(2)
.build();
return config;
}
// private void manipulateConfig(Config config, String newParam1) {
// config.param1 = newParam1;
// }
public static void main(String[] args) {
ConfigTest configTest = new ConfigTest();
Config config = configTest.getConfig();
System.out.println(config);
Config.Builder anotherBuilder = new Config.Builder();
anotherBuilder.modifyParm2(config, 3);
System.out.println(config);
// configTest.manipulateConfig(config, "val11");
}
}
Output of running ConfigTest:
Config{param1=Val1, param2=2}
Config{param1=Val1, param2=3}