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
Related
To my knowledge, normally in Java, something that is static means you can't create an instance of it. But if that is the case, why can you create an instance of a static nested class? Doesn't that defeat the purpose of something being static?
To my knowledge, normally in Java, something that is static means you can't create an instance of it.
That's not right. static is more "does not belong to any specific instance, but to the type/class itself".
Think of a static class in the context of the enclosing class. A static class is a static member, meaning that the nested class is not tied to any particular instance of the enclosing class.
The implication of this is that you can create an instance of the nested class without having to create an instance of the outer class first.
something that is static means you can't create an instance of it.
That's not true. Not only can you not create instances of static fields, you can't create instances of non-static fields either, because it is a field, not a class.
static just means that you don't need to create an instance of the surrounding class to access it. static members belong to the class itself, instead of instances of that class.
With this definition, static classes makes total sense.
Instances of static classes can be created without creating instances of their outer class:
class Outer {
static class Inner {}
}
Outer.Inner obj = new Outer.Inner(); // no Outer instances created!
Whereas instances of non-static inner classes cannot:
class Inner {
class Outer {
}
}
Inner inner = new Inner(); // I have to create this instance, otherwise it wouldn't compile
Inner.Outer outer = inner.new Outer();
Imagine a situation where you have a method in your nested static class and you want to call that method.
Refer to this snippet below:
class OuterClass
{
// static nested class
static class StaticNestedClass
{
void display()
{
System.out.println("Static Nested Class Display Method");
}
}
static void display()
{
System.out.println("Outer Class Display Method");
}
public static void main(String[] args)
{
// accessing a static nested class
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
nestedObject.display(); // This calls the display() method of the static nested class
OuterClass.display(); // This calls the display() method of outer class
}
}
How will you access the display() of static nested class without creating an object of it.
Java allows to create an instance of static nested class so that we can access the methods defined within that class.
Hope it helps!!!
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.
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();
If we have a code...
public class Hello
{
public static void main(String args[])
{
Outer obj=new Outer();
obj.method1();
}
}
class Outer
{
void method1()
{
class Inner
{
}
}
}
I wanted to know,when the Inner class will be loaded by the ClassLoader.
Is it loaded at the time the method1() is called,or at the time when we will be creating its instance?And the class Inner is not performing any operation in method1(),its an empty class.Also,I wanted to know,how to create an instance of inner class in the above example?
Class Outer.Inner will be loaded the first time another class that refers to it as a variable type, method parameter type, method return type, superclass type, type parameter bound, or target type of an initializer or static method, or host class of a static variable reference is loaded. In your example, I would expect it never to be loaded.
Also,I wanted to know,how to create an instance of inner class in the above example?
As it is written, class Outer.Inner is accessible only inside method Outer.method1(), therefore it can be instantiated only within that method. There, you can just use new Inner(). If you want it to be instantiable from elsewhere then move its declaration out of the method body:
class Outer
{
class Inner
{
}
void method1()
{
}
}
That's better form for a named inner class anyway. It will not change when or whether Outer.Inner is loaded.
With that change, you can instantiate Outer.Inner anywhere within a constructor or instance method of Outer via the form new Inner(). If, however, you want to instantiate one from a different class, or in a static method of class Outer, then it's a bit trickier. The important thing to realize is that each instance of Outer.Inner needs an associated instance of Outer. This is determined from context when the instantiation is performed in an instance method of Outer, but if it is performed without such a context then the syntax is:
public static void main(String args[])
{
Outer obj=new Outer();
Outer.Inner inner = obj.new Outer.Inner();
}
Quoting from Section 12.4.1 of the JLS :
A class or interface type T will be initialized immediately before the
first occurrence of any one of the following:
T is a class and an instance of T is created.
A static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant
variable (§4.12.4).
T is a top level class (§7.6) and an assert statement (§14.10)
lexically nested within T (§8.1.3) is executed.
Therefore, a class (regardless of whether is a nested class) will follow the same rules. In your particular case, Inner will not be loaded until an instance of the class is created.
To answer your second question, you can only create an instance of Inner inside method1 since Inner is a method local class whose scope is limited to method1 :
void method1()
{
class Inner
{
public Inner()
{
System.out.println("inner()");
}
}
Inner inner = new Inner();
}
To achieve the inner class, you need object anyway. If you call method1() like this, inner class never be called.
But if you define some object in method1() or public Outer() constructor, you can get result from inner class.
From Oracle's Java tutorials I've found this text:
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.
Static nested classes are accessed using the enclosing class name:
OuterClass.StaticNestedClass
For example, to create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
I thought it is not possible to instantiate a static class, so I don't really understand the sentence in bold.
Do you have any idea what it means?
You are either confusing static with abstract as kihero says, or you are muddling the concept with a class that has static methods (which is just a class that happens to have static methods).
A static nested class is just a nested class that doesn't require an instance of its enclosing class. If you are familiar with C++, all classes in C++ are "static" classes. In Java, nested classes are not static by default (this non-static variety is also called an "inner class"), which means they require an instance of their outer class, which they track behind the scenes in a hidden field -- but this lets inner classes refer to fields of their associated enclosing class.
public class Outer {
public class Inner { }
public static class StaticNested { }
public void method () {
// non-static methods can instantiate static and non-static nested classes
Inner i = new Inner(); // 'this' is the implied enclosing instance
StaticNested s = new StaticNested();
}
public static void staticMethod () {
Inner i = new Inner(); // <-- ERROR! there's no enclosing instance, so cant do this
StaticNested s = new StaticNested(); // ok: no enclosing instance needed
// but we can create an Inner if we have an Outer:
Outer o = new Outer();
Inner oi = o.new Inner(); // ok: 'o' is the enclosing instance
}
}
Lots of other examples at How to instantiate non static inner class within a static method
I actually declare all nested classes static by default unless I specifically need access to the enclosing class's fields.
Static nested classes are themselves not static at all. In java, no class is static. Static keyword in static nested classes implies that it is another static member of the outer class. But it is just another raw class . Thats why we can instantiate this class
You are confusing static with abstract. Abstract classes can not be instantiated. static is not a valid qualifier for top level classes, but the meaning for inner classes is the one you quoted.
I guess you misunderstood the static class a little bit.
It's true that every abstract class and interface cannot be instantiated, but you do can instantiate an static class.
One thing you should notice is that every static class is a nested static class.
You cannot just create a static class, as you can see:
try to create a new class in eclipse
A static class always belongs to the "parent class" which encloses it, and the difference between static and non-static class is:
You can refer to the child static class just like a static property of the "parent class":
ParentClass.NestedStaticClass nestedstatic = new ParentClass.NestedStaticClass();
but you can only make reference to the non-static nested class by instantiating a parent class, like this:
ParentClass parent = new ParentClass();
ParentClass.NestedClass nested = parent.new NestedClass();
The difference is just like that between the static and non-static field.
Too long, didn't read: Every Concrete Class can be instantiated.
We should not expect a Concrete Static Nested Class to function identically as Static variables and Static methods, when it comes to calling and instantiation.
What do I mean by that? When we create variables and methods they can be either static or non-static. The keyword in the previous sentence is "either".
Static meaning they belong to the class and we must call them directly, like this:
Class.staticVariable();
Class.staticMethod();
Non-static meaning they belong to an Instance of that Class and we must call them like this:
Class obj = new Class();
System.out.println(obj.nonStaticVariable);
obj.nonStaticMethod();
But here we are talking about a Class, not a variable or a method.
Every Concrete Class can be instantiated. Thus we should not expect a Concrete Static Nested Class, to not be instantiable.