Inner class instantiation - java

An inner class is said to be a member of the outer class. Does that mean that whenever an object of the outer class is created, an instance of inner class is also created implicitly?

No. An instance of the inner class is created only when you instantiate it.
Note that the constructor of the inner class requires an instance of the outer class (although this is masked by the compiler). This is true for non-static nested classes. Static nested classes can be instantiated without a parent instance (since they are static)

There are different types of inner classes each acting differently.
Static member classes
Member classes
Local classes
Anonymous classes
You can find a good overview of all of them here :
http://www.javaworld.com/javaworld/javaqa/2000-03/02-qa-innerclass.html

It means that you need an instance of the outer class before you can have an instance of the inner class

Related

Java inner classes and static methods or fields

Why can't inner classes have static (non-final) fields and methods?
This question has been posted before but the posted answers were: it's a design decision or because inner classes happen in the context of the outer class and cannot declare static methods.
Yet these answers do not clarify my question. What would be the consequences of allowing static fields and methods on inner classes? My guess is that both restrictions are connected. Since static methods would require access to other static methods and non-final static variables of the inner class or even from the outer class (to be able to change internal states), this would lead a inner class to behave like a static one. The JVM could limit access from static methods in inner classes to static methods and data inside the inner class, though. Yet this raises the question: why can't we declare static non-final variables inside inner classes?
Is this design or there are problems?
Kind regards
Declaring static variables in non-static inner class seems contradictory to intend of creating inner non-static class.
If you declaring some variables and methods static you do it when it make sense to access them without creating instance of class, if you declaring inner class non-static its instance type, so intent is to access it via its instance not staticly. If you declare inner class static, therefore separate it from outer class, you can declare variables and methods static.
You asked what would be consequences if java allowed you to declare static methods/fields in inner non-static classes. Well probably there would be none. But it just doesn't make sense, therefore it's a design choice.
To answer why... ->
Inner class object is strongly associated with Outer class object that means without existing Outer class object there is no chance of existing Inner class Object, so defining any static variable/method inside Inner class would not fulfill this requirement
In case of static nested class -> Inner class object is NOT strongly associated with Outer class object

Must Inner classes have a reference to the enclosed class?

I have an inner class (non-static) which is using a reference to an enclosing class in its initialization. Will the inner class keep a reference to the enclosing class now?
class Enclosing {
class Inner {
private final ABC innerField = outerField.computeSomething();
}
private final XYZ outerField = something();
}
UPDATE
I am very much aware that one can reference the outer class with Enclosing.this.
But, if the class doesn't use the reference, must the reference be there after compilation? Is it necessary even if the reference is only used in the initialization?
Where does it say that an inner class always holds a reference to the outer class?
A non-static nested class always holds a reference to the enclosing class. In your example, you can reference the enclosing class from Inner as Enclosing.this.
JLS 8.1.3 "Inner classes and Enclosing Instances":
"An instance i of a direct inner class C of a class O is associated with an instance of O, known as the immediately enclosing instance of i. The immediately enclosing instance of an object, if any, is determined when the object is created (§15.9.2)."
Yes. An inner class (or non-static nested class) is just like any other instance member of the outer class, and as such always needs a reference of the enclosing class.
Where does it say that an inner class always holds a reference to the outer class?
In the same place it defines the Outer.this syntax. The existence of this syntax is the existence of the reference. There is nothing to suggest that it is suppressed if not used.
There are two cases of nested-classes:
static nested-classes. The nested-class does not keep reference to the outer-class.
non-static nested-classes. The nested-class does keep a reference to the outer-class.
The case of a static nested-class that extends the outer-class is not as interesting as the
non-static nested-class extending the outer-class.
An important thing to remember is that non static nested classes are simply called inner classes.

Why can we access a variable in an inner class from an outer class?

If I declare a variable as private in an inner class, the variable is visible to the outer class. I am unable to understand the logic here. Shouldn't it ideally be only accessible within an inner class?
I think the answer is subjective as the question basically seems to be asking why Sun/Oracle's language designers decided to allow a certain behavior.
That said, here is an attempt at an answer...
First some terminology, a class declared within a class is a nested class. An inner class is a non-static nested class which must reside within an instance of the outer class. So the inner class is a part of the outer class and in that sense, all members of the inner class are to an extent members of the outer class.
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.
Another thought is that the valid use cases for an inner class preclude the necessity to allow the inner class to hide members from the outer class. That is, there is no notion that the outer class would not be coupled to the inner class.
Why allow private at all then? Because private members can still be hidden from other classes which may gain access to an instance of an inner class.

Why would i want to create an instance of a static class in java?

The Java Tutorial says that the static nested classes are accessed by using the name of the enclosing class like new EnclosingClassNameHere.StaticNestedClassNameHere()
Why would i want to create an instance of a static class at all? Can somebody please explain?
"static" in this case can be misleading. What it really means is that the class can exist independently. Non-static inner classes can't exist without an instance of the enclosing class.
IMO, when you start using an inner class outside the class that it's in, you need to consider moving it and making it its own top level class. There are very few cases where the relationship between the classes is so tightly coupled that you need to keep it as an inner class.
In your code example:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
You're creating a stand-alone instance of StaticNestedClass.
If it wasn't static, you couldn't do that. You could only create instances of StaticNestedClass() from an instance of OuterClass.
If you moved it to its own .java file, you could treat it nearly identically:
StaticNestedClass notNestedAnymore = new StaticNestedClass();
As to your real question: Why would you want to create an instance of it? For the same reason that you create instances of any class - it does some piece of work that you need.
There is nothing confusing with this code. Static nested class is just a way to introduce yet another namespace.
By creating a static nested class you express very strong relationship between outer and inner class. Typically nested class is a helper or a part of the outer class. For instance when you create a Tree class, Node class is a good candidate for a nested static class. The Tree.Node clearly explains the purpose of the Node class.
In fact, static keyword usage is consistent with static fields. In both cases you can access static entity without an instance of enclosing class. When it comes to static classes it basically means: "I can create an instance of this static nested class without having an instance of outer class". By default (when static keyword is not used) the nested class becomes inner class. In this case you cannot simply write:
new OuterClass.StaticNestedClass();
Instead you are required to pass OuterClass instance with a bit obscure syntax:
OuterClass outerClassInstance = new OuterClass();
outerClassInstance.new InnerClass();
Fortunately when new InnerClass() is executed inside an OuterClass body, this is implictly used as enclosing instance.
In java inner classes have an implicit reference to an instance of the outer class. This way you can access members of the outer class directly, which is usefull in annonymous classes used for callbacks.
class A{
private int a = 3;
class Inner{
Inner(){
System.out.println(a);//also A.this.a
}
}
static class StaticInner{
StaticInner(){
System.out.println(a);//FAILS
}
}
}
Declaring an inner class static simply removes this implicit reference and that is the only difference between static and non static inner classes.

Java scoping rules and inner classes

All the crazy Java scoping rules are making my head spin and the public static void nonsense isn't helping matters. So far all the programming languages I have used either lexical scoping or some approximation of it without any access modifiers, i.e. inner stuff captures outer stuff and has access to the outer stuff as long as the inner stuff exists.
So how do I make sense of the scoping rules for inner classes in Java? Do they get access to variables declared in the outer class or is there some weird edge cases I have to worry about because of all the public static private stuff floating around?
Static nested classes1 are exactly like external classes except that they have access to all members of the outer class, regardless of access qualifier. They exist apart from any instance of the outer class, so need a reference to an instance in order to access any instance variables or non-static methods of the outer class.
Non-static nested classes (called inner classes) come into existence only in the context of an instance of the outer class. When constructed, they have a second this field automatically generated, which you can access from within the inner class using the syntax Outer.this. Each instance of the inner class is enclosed by a single instance of the outer class. Again, all the access privileges of static nested classes apply to inner classes. But since they already have an instance of the outer class available, they can automatically access instance variables and methods of the outer class.
For a nice (and very detailed) discussion of inner classes and access specifiers, you can read through the Inner Class Specification. It describes, among other things, how a nested class gets access to private members of its outer class(es). A gentler read is the Nested Classes tutorial.
An off-topic aside: Suppose you have this class structure:
public class O {
public O() { ... }
public class I { // an inner class
public I() { ... }
...
}
...
}
and you've created an instance of O:
O outer = new O();
Now suppose you want to create an instance of O.I. you can't just use new O.I() because the new instance of I needs to be enclosed by a specific instance of O. For this, Java provides the following syntax:
O.I inner = outer.new O.I();
Then inner will then have its second this field set to refer to outer.
Note that this "qualified new operator" syntax is only used for inner classes; it would be unnecessary (in fact, an error) if I were a static nested class.
1 You'll often come across the phrase "static inner class" (including, embarrassingly, in an earlier version of this answer). This is incorrect terminology. In Java, "inner classes" are specifically non-static nested classes.
You have to differenciate:
Static inner classes have access to all static members outside their declaration.
Instance inner classes have access to all class members outside their declaration, AND to final fields in the function they are declared in.
Have in mind that a non-static inner class also has a hidden variable with the instance of the outer class, to access the members there. And that all referenced final fields (therefore they must be final) are copied into the inner class in other hidden member variables when the inner class is instantiated.
Example:
public void doStuff(final int a, int b) {
final int c; // Can be referenced
int d; // Cannot be referenced, not final
executer.execute( new Runnable() {
public void run() {
System.out.println("a: "+a+" c: "+c);
}
}
b++; // Not final, not referencable
System.out.println(b);
}
I don't know if it helps, but from the java tutorials:
Static Nested Classes
As with class methods and variables, a static nested class is associated with its outer class. And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class — it can use them only through an object reference.
Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
Inner Classes [Non-Static Nested class?]
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.
You should check the java tutorial on nested classes.
Rules of the Inner classes in Java
In Java it is possible to define a class inside another class such classes are called nested classes or inner class.
There are 3 types of the Inner classes Instance Inner class, static inner class and anonymous inner class
If the Inner class is declared as instance inner class then it can access all of the members of the outer enclosing class including private members
If the Inner class is declared as static then it can only access the static members of the outer class (including the private static members). But it can NOT access the instance members
Consider that there is a variable x is defined in both the outer class and the instance inner classes then general form for accessing the variable from the inner class is this.x for the inner x and OuterClassname.this.x for the outer x.
You can also define an inner class inside any method or any other block
The general form for instantiating the inner class from outside the outer class is
Outer.Inner ob = new Outer.new Inner();
The general form for instantiating the inner class from outside the outer class is (if the inner class is declared as static)
Outer.Inner ob = new Outer.Inner();
The Inner classes can be declared with any of the access modifier keywords
If the Inner class is declared as private then it can NOT be instantiated from outside the outer class. Also in this case you can NOT access the members of the Inner class from outside the outer class even you have an object reference and even if the members of the private inner class are declared as public.
If the Inner class is declared as instance inner class then it can also access the superclass members of the outer class through the general statement
Outer.super.variable; Outer.super.method(params);
Rules for inner class
Outer class accessed by inner class
Inner class can't be accessed by outer class
The inner class members only used the methods and members within the class only access the fulled information
Method Scoped inner classes:-
Can only access the final members of the outer class.

Categories