When I create an instance of inner class, I use this code.
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass inerClass = outerClass.new InnerClass();
But I don't understand how outerClass.new InnerClass() works, why we use .new it like new its inner class, I understand it is not, but I do not understand the syntax.
An inner class is POJO. So, when you look in the target directory, you see 2 (two) class files.
Therefore to create an instance of the inner class you use new.
OuterClass outerClass = new OuterClass(); // create instance
OuterClass.InnerClass inerClass = outerClass.new InnerClass(); // innerClass has `this` to outerClass instance
It means that InnerClass is not a static (i.e. has this reference to an object of OuterClass) and instance of OuterClass should be created prior to it.
OuterClass.InnerClass inerClass = new OuterClass.InnerClass();
It means that InnerClass is a static (i.e. has not this reference to an object of Outerlass) and it means, this is absolutely the same (from the JVM perspective) like two separate files with class OuterClass and class InnterClass.
Related
I'd like to create a subclass accessible only from an instance of the superclass, but not from the superclass itself, to be sure that the superclass' variables have been initialized.
For example:
public class SuperClass
{
int num;
SuperClass(int number){
num = number;
}
//Make this\/ accessible from instance only
class SubClass
{
SubClass(){}
public int read(){
return num;
}
}
}
In another file:
public void err(){
SuperClass.SubClass obj = new SuperClass.SubClass(); //Error! Superclass is not an instance
System.out.println(obj.read());
}
public void right(){
SuperClass sup = new SuperClass(3);
SuperClass.SubClass obj = new sup.SubClass(); //Correct, sup is an instance
System.out.println(obj.read()) //Print 3
That's not possible. Non-static inner classes have to be instantiated through an instance of an outer class. See this link for more info.
Inner Classes
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.
Objects that are instances of an inner class exist within an instance of the outer class. Consider the following classes:
class OuterClass {
...
class InnerClass {
...
}
}
An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance.
To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
There are two special kinds of inner classes: local classes and anonymous classes.
check the link
This question already has answers here:
How to instantiate non static inner class within a static method?
(4 answers)
Closed 5 years ago.
class Outer{
int i = 60;
class Inner{
void display(){
System.out.println(i);
}
}
public static void main(String args[]){
Inner o = new Inner();
o.display();
}
}
Main function does instantiate it's class which are non-static whereas when it comes to instantiating inner class(non-static), java compiler shows up with an error(like the above code). Why?
Edit: I am not asking how to instantiate inner class. I just want a logical reason why main() doesn't instantiate it's inner class while the following function does.
class Outer{
int i = 60;
void show(){
Inner k = new Inner();
k.display();
}
class Inner{
void display(){
System.out.println(i);
}
}
public static void main(String args[]){
Outer o = new Outer();
o.show();
}
}
You need an (enclosing) instance of Parent class as child class instance can't exist on it's own, e.g.:
Outer outer = new Outer();
Inner o = outer.new Inner();
o.display();
Outer class must be instatiated as well:
Inner o = new Outer().new Inner();
You need to have a reference of the parent class.
public static void main(String args[]){
Inner o = new Outer().new Inner();
o.display();
}
From 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.
Inner Classes
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.
So if you want to be able to instantiate an inner class, you need to have an instance of the outer class. In instance methods you don't need it because you're always referring to 'this'
The Java docs says:
An instance of InnerClass can exist only within an instance of
OuterClass and has direct access to the methods and fields of its
enclosing instance.
To instantiate an inner class, you must first instantiate the outer
class. Then, create the inner object within the outer object with this
syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
So you can try like:
Inner o = new Outer().new Inner();
Because the static methods and attributes of a Class belong to the Class and not at an instance of the Class. For that reason can interact only with other static methods and attributes of the Class.
When we try to instantiate an Inner class (aka: non-static Nested class) in java, say we do that in two cases:
1.in a main method in the same file of the outer Class in which we have two options: (ex:)
public class Test1
{
class InnerClass
{
}
public static void main(String[] args)
{
InnerClass inner = new Test1().new InnerClass();
}
}
or :
public class Test1
{
class InnerClass
{
}
public static void main(String[] args)
{
Test1.InnerClass inner = new Test1().new InnerClass();
}
}
In a another class (say different file), then we have the second option only and using the first option requires us (of course) to import the InnerClass..,
Q: could you please explain why do we have the first option (without any import required) in the first case (the main method in the same file)?
Edit:
I guess the answer to the first question is some how related to the core idea of inner classes. but then +Q:
Q: Isn't an inner class a regular-member of an outer class, so if the inner class is not declared static (static nested class) then I suppose it is a non-static member and consequently its reference type, so why are we able to declare it within a static context (static method) ?
Simply, it is because when you instantiate the inner class from a main method outside the class in which the inner class is present, the Java compiler has no way on knowing inside which class lies that inner class. Hence you have to do
Test1.InnerClass innerClassObject = ...
instead of
InnerClass innerClassObject = ...
An instance of InnerClass can exist only within an instance of
OuterClass and has direct access to the methods and fields of its
enclosing instance.
To instantiate an inner class, you must first instantiate the outer
class. Then, create the inner object within the outer object with this
syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
From Oracle Docs : https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
I understand that an Inner Class it's non-static and a static method from the Outer Class can't reference it.
I have this code, that doesn't work, and I understand why that doesn't work.
class OuterClass {
class InnerClass{}
public static void outherMethod() {
InnerClass i = new InnerClass();
}
}
But then I have this other code, that DOES work, but I don't understand why it's different from the first one. Why does it work?
class OuterClass {
class InnerClass{}
public static void outherMethod() {
InnerClass i = new OuterClass.new InnerClass();
}
}
Thanks in advance!
EDIT: it's not duplicated because it isn't the same question. I'm not asking about static nested classes, I'm asking about static methods and inner classes
An inner class always requires an instance of the enclosing class in order to be instantiated.
A static method of OuterClass doesn't have an instance of OuterClass, so you can't create an instance of InnerClass without supplying an enclosing instance (of OuterClass).
InnerClass i = new InnerClass();
would work only from within an instance method of OuterClass.
InnerClass i = new OuterClass().new InnerClass();
works from within a static method since you are creating an instance of OuterClass and use it as the enclosing instance for an instance of InnerClass.
The key point to note here is Inner class is a member of Outer class.
So without an instance of it, you can't access it's members.
From docs directly
An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance.
To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
This question already has answers here:
Java inner class and static nested class
(28 answers)
Closed 8 years ago.
class Outer {
class Inner {
}
}
public class Demo {
public static void main(String args[]) {
Outer o = new Outer();
Outer.Inner inner = o.new Inner();
}
}
the way I create a reference for Inner class object is something like accessing static member in Outer class ? could you please explain the mechanism behind this ?
Not sure exactly what you are asking, but your code is valid.
You can only instantiate Inner if you have an instance of Outer, so you call only call Inner's constructor in the context of an instance of Outer, hence
Outer o = new Outer();
Inner i = o.new Inner();
works, but
Inner i = new Outer.Inner(); //bad
Inner i = Outer.new Inner(); //bad
are both trying to access Inner in a static way, and will not compile.
If you want create instances of Inner without first creating an instance of Outer, then Inner needs to be static
the way I create a reference for Inner class object is something like accessing static member in Outer class
Not at all - since you are using an instance of the Outer to access the constructor of the Inner, this is very much like accessing an instance member of the Outer class, not its static member. The name of the Inner class in the declaration is qualified with the name of its outer class Outer in order to avoid naming conflicts with top-level classes.
The reason for that is easy to understand: Inner is a non-static inner class, so it needs to reference an Outer. It does so implicitly, but the reference must be passed to the constructor behind the scene. Therefore, you call a constructor of Inner on an instance of Outer.
The syntax for making instances of static classes is similar to the syntax for making instances of regular classes, except the name of the nested class must be prefixed with the name of its outer class - i.e. following the static syntax:
class Outer {
static class Inner {
}
}
public class Demo {
public static void main(String args[]) {
Outer.Inner inner = new Outer.Inner();
}
}
You're actually accessing an inner class in a non-static way. A static inner class is actually different - the compiler makes a top-level class for it that is hidden from the programmer, which then works similarly to the way of instantiation that you have posted for the inner class.
You have to declare this way because since the inner class is non-static, it needs an instance of the outer class to make an instance of the inner class.
Outer o = new Outer();
is the required instance for the outer class.
Outer.Inner inner = o.new Inner();
is required for the instance of the inner class.
The reason why this looks weird is because you declared non-static inner class. That means that inner class will have access to instance variables in the enclosing class and would have to have a this reference to it.
Think of it this way: non-static inner class is a part of the enclosing class's instance like any other field. You need to specify a particular instance in order to create an object.
So just like you'd initialize a regular field like this (don't actually do that, it's bad):
o.someField = new Object(), you initialize inner class the way you did.