My question pertains to the code at the bottom of this post.
I don't understand why the compiler doesn't give an error for the line below. Why would it let you refer to something inside the class (in this case I'm referring to
ClassWithInnerClass.MyInnerClass
) unless it were static?
ClassWithInnerClass.MyInnerClass mic = cwic.retMyInnerClass();
To illustrate why I'm asking, I created 2 ints ("regularInt" and "staticInt") inside class "ClassWithInnerClass". The compiler let me set the value of "staticInt" from within main whereas it wouldn't let me do so w/ "regularInt" (which is why I commented that line out). Don't get me wrong though - I understand the reasons why the compiler behaves as it does for "regularInt" and "staticInt". I understand that a static variable can be accessed without instantiating a class (and that there's only 1 created no matter how many classes are instantiated). I also understand that, to access a non-static variable, you need to instantiate a class. My question arises only because of trying to extend that logic to MyInnerClass.
I can already take a guess that the answer is going to be something like, "the reason it works this way is because class 'MyInnerClass' is just a declaration NOT a definiton". I guess I just want confirmation of this and, if possible, some reasoning behind this logic.
HERE'S THE CODE...
class CreateInnerClasses {
publicstaticvoid main (String args[]) {
ClassWithInnerClass cwic = new ClassWithInnerClass();
ClassWithInnerClass.MyInnerClass mic = cwic.retMyInnerClass();
//ClassWithInnerClass.regularInt = 5;
ClassWithInnerClass.staticInt = 10;
mic.printIt();
}
}
class ClassWithInnerClass {
publicint regularInt ;
staticpublicint staticInt;
class MyInnerClass {
void printIt() {
System.out.println("Inside ClassWithInnerClass.myInnerClass");
}
}
MyInnerClass retMyInnerClass () {
returnnew MyInnerClass();
}
}
A class can be thought of as a blueprint* that the JRE uses to create objects. So you can't think of a class in the same manner as you think of static and instance variables. It isn't "data" so it doesn't "belong" to the outer class in the same way that a static variable does.
twc
* Some people prefer to call the class a "factory" that creates the objects, but several college profs that I've corresponded with tell me that the blueprint analogy is probably a bit more accurate since the class is "read" by the JRE.
By the way, I find it interesting that this code won't compile because of an error on this line...
SomeClassWithAnInnerClass.InnerClass ic = new SomeClassWithAnInnerClass.InnerClass();
It seems like there's a problem with referring to an inner class that hasn't been instantiated on the right-side of the expression but not on the left-side. I don't understand that either.
class ReturnRefToInnerClass {
publicstaticvoid main (String args[]) {
SomeClassWithAnInnerClass.InnerClass ic = new SomeClassWithAnInnerClass.InnerClass();
}
}
class SomeClassWithAnInnerClass {
class InnerClass {
void printSomething () {
System.out.println("SomeClassWithAnInnerClass.InnerClass.printSomething");
}
}
public InnerClass retInnerClass() {
returnnew InnerClass();
}
}
(I'm not a native english speaker, so forgive me for the language faults I make.)
I think about this as follows:
Instances of non-static inner classes have access to the fields of the enclosing (outer) class. To make this possible, every instance of a non-static inner class has an implicit reference to the instance of the outer class. In your example: an instance of SomeClassWithAnInnerClass.InnerClass needs for creation a reference to its instance of SomeClassWithAnInnerClass. Note that inside the code of InnerClass you can reference the "outer class instance" by SomeClassWithAnInnerClass.this.
So how to make an instance of InnerClass from outside its outer class?
The following code will do it, but it is rarely used:
// first create an instance of the outer class:
SomeClassWithAnInnerClass outerInstance = new SomeClassWithAnInnerClass();
// now use the "new" operator on this instance to create the inner class instance
SomeClassWithAnInnerClass.InnerClass innerInstance = outerInstance.new InnerClass();