Why can you create instance of static nested class? - java

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!!!

Related

Innerclass belongs to the instance of the Outerclass then why it can be declared static and how we are able to make the instance of static class?

I am learning Java and a bit confused in the concept of Inner class being declared Static. As far as I have learned Declaring any member static means it is belongs to the class level and not the instance of the class and Inner Class is the instance of the Outer Class and we can instantiate it as many times as we want.
So, how we can declare it as Static? It contradicts the concept of static keyword. And By declaring the class static Shouldn't all the members of that class by default becomes static ? But it is not the case. Why?
class Outerclass{
static int a=10;
static class Innerclass{
System.out.println(a);
}
}
Imagine you have this:
public class Outer {
class InstanceInner {
}
static class StaticInner{
}
public static void main(String[] args) {
Main main = new Main();
Inner instanceInner = main.new Inner();
Main.StaticInner staticInner = new Main.StaticInner();
}
}
Now:
InstanceInner instanceInner = main.new InstanceInner();
creates instance of the inner class, that is instance member of Main class; i.e. every instance of InstanceInner will be belonging to the particular instance of Main. Like other instance fields or methods.
This line, however:
Main.StaticInner staticInner = new Main.StaticInner();
creates instance of the StaticInner class, that is static member of the Main; i.e. every instance of StaticInner will be a static member of Main class.
Bear in mind:
a static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class;
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.

Instantiating an inner class within a main method

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

Can a static nested class be instantiated in Java?

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.

Static nested classes

I'm reading 'Thinking of Java' and I have encountered some weird example (for me)
class StaticTest {
static class StaticClass {
int i = 5;
}
}
public class I {
public static void main(String[] args) {
// TODO Auto-generated method stub
StaticTest.StaticClass t = new StaticTest.StaticClass();
}
}
How is it possible to create instance of static class? Is it some exception to the rule 'You can't create instance of static class'?
Thanks in advance
In case of classes, the modifier static describes the relationship between the outer and the inner class.
If the inner class is not static, it is bound to an instance of the outer class and threrefore cannot be created from outside.
A static inner class can completely be created without an instance of the outer class, but has privileged access to members of the class.
A static class is nothing more than a class, but with the difference to where it's code is placed.
Therefore, you can create instances of static classes. The only difference is you have to provide the name of the class, which nests the static one (as shown on your code snippet).
StaticTest.StaticClass t = new StaticTest.StaticClass();
From Java docs regarding creating instance for static nested classes.
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.
For example, to create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
in this case static describes the relation b/w inner and outer class
it doesnt mean the inner class is static
a static nested class doesnt invoke non-static methodes or access non-static fields of an instance of class within which it is nested

Static nested class in Java, why?

I was looking at the Java code for LinkedList and noticed that it made use of a static nested class, Entry.
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
What is the reason for using a static nested class, rather than an normal inner class?
The only reason I could think of, was that Entry doesn't have access to instance variables, so from an OOP point of view it has better encapsulation.
But I thought there might be other reasons, maybe performance. What might it be?
Note. I hope I have got my terms correct, I would have called it a static inner class, but I think this is wrong: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
The Sun page you link to has some key differences between the two:
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
...
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.
There is no need for LinkedList.Entry to be top-level class as it is only used by LinkedList (there are some other interfaces that also have static nested classes named Entry, such as Map.Entry - same concept). And since it does not need access to LinkedList's members, it makes sense for it to be static - it's a much cleaner approach.
As Jon Skeet points out, I think it is a better idea if you are using a nested class is to start off with it being static, and then decide if it really needs to be non-static based on your usage.
To my mind, the question ought to be the other way round whenever you see an inner class - does it really need to be an inner class, with the extra complexity and the implicit (rather than explicit and clearer, IMO) reference to an instance of the containing class?
Mind you, I'm biased as a C# fan - C# doesn't have the equivalent of inner classes, although it does have nested types. I can't say I've missed inner classes yet :)
There are non-obvious memory retention issues to take into account here. Since a non-static inner class maintains an implicit reference to it's 'outer' class, if an instance of the inner class is strongly referenced, then the outer instance is strongly referenced too. This can lead to some head-scratching when the outer class is not garbage collected, even though it appears that nothing references it.
Static inner class is used in the builder pattern. Static inner class can instantiate it's outer class which has only private constructor. You can not do the same with the inner class as you need to have object of the outer class created prior to accessing the inner class.
class OuterClass {
private OuterClass(int x) {
System.out.println("x: " + x);
}
static class InnerClass {
public static void test() {
OuterClass outer = new OuterClass(1);
}
}
}
public class Test {
public static void main(String[] args) {
OuterClass.InnerClass.test();
// OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside.
}
}
This will output x: 1
static nested class is just like any other outer class, as it doesn't have access to outer class members.
Just for packaging convenience we can club static nested classes into one outer class for readability purpose. Other than this there is no other use case of static nested class.
Example for such kind of usage, you can find in Android R.java (resources) file.
Res folder of android contains layouts (containing screen designs), drawable folder (containing images used for project), values folder (which contains string constants), etc..
Sine all the folders are part of Res folder, android tool generates a R.java (resources) file which internally contains lot of static nested classes for each of their inner folders.
Here is the look and feel of R.java file generated in android:
Here they are using only for packaging convenience.
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.techpalle.b17_testthird;
public final class R {
public static final class drawable {
public static final int ic_launcher=0x7f020000;
}
public static final class layout {
public static final int activity_main=0x7f030000;
}
public static final class menu {
public static final int main=0x7f070000;
}
public static final class string {
public static final int action_settings=0x7f050001;
public static final int app_name=0x7f050000;
public static final int hello_world=0x7f050002;
}
}
Well, for one thing, non-static inner classes have an extra, hidden field that points to the instance of the outer class. So if the Entry class weren't static, then besides having access that it doesn't need, it would carry around four pointers instead of three.
As a rule, I would say, if you define a class that's basically there to act as a collection of data members, like a "struct" in C, consider making it static.
From http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html:
Use a non-static nested class (or inner class) if you require access
to an enclosing instance's non-public fields and methods. Use a static
nested class if you don't require this access.
Simple example :
package test;
public class UpperClass {
public static class StaticInnerClass {}
public class InnerClass {}
public static void main(String[] args) {
// works
StaticInnerClass stat = new StaticInnerClass();
// doesn't compile
InnerClass inner = new InnerClass();
}
}
If non-static the class cannot be instantiated exept in an instance of the upper class (so not in the example where main is a static function)
One of the reasons for static vs. normal have to do with classloading. You cannot instantiate an inner class in the constructor of it's parent.
PS: I've always understood 'nested' and 'inner' to be interchangeable. There may be subtle nuances in the terms but most Java developers would understand either.
Non static inner classes can result in memory leaks while static inner class will protect against them. If the outer class holds considerable data, it can lower the performance of the application.
JVM knows no nested classes. Nesting is just syntactic sugar.
Below images shows Java file:
Below images show class files representation of the java file :
Notice that 2 class files are generated, one for parent and another for nested class.
Non-static nested class' objects have access to the enclosing scope. That access to the enclosing scope is maintained by holding an implicit reference of the enclosing scope object in the nested object
Nested class is a way to represent the intent that the nested class type represents a component of the parent class.
public class Message {
private MessageType messageType; // component of parent class
public enum MessageType {
SENT, RECEIVE;
}
}
class Otherclass {
public boolean isSent(Message message) {
if (message.getMessageType() == MessageType.SENT) { // accessible at other places as well
return true;
}
return false;
}
}
private static nested class represents Point#3 & the fact the nested type can only be the subcomponent to the parent class. It can't be used separately.
public class Message {
private Content content; // Component of message class
private static class Content { // can only be a component of message class
private String body;
private int sentBy;
public String getBody() {
return body;
}
public int getSentBy() {
return sentBy;
}
}
}
class Message2 {
private Message.Content content; // Not possible
}
More details here.
I don't know about performance difference, but as you say, static nested class is not a part of an instance of the enclosing class. Seems just simpler to create a static nested class unless you really need it to be an inner class.
It's a bit like why I always make my variables final in Java - if they're not final, I know there's something funny going on with them. If you use an inner class instead of a static nested class, there should be a good reason.
Using a static nested class rather than non-static one may save spaces in some cases. For example: implementing a Comparator inside a class, say Student.
public class Student {
public static final Comparator<Student> BY_NAME = new ByName();
private final String name;
...
private static class ByName implements Comparator<Student> {
public int compare() {...}
}
}
Then the static ensures that the Student class has only one Comparator, rather than instantiate a new one every time a new student instance is created.
Adavantage of inner class--
one time use
supports and improves encapsulation
readibility
private field access
Without existing of outer class inner class will not exist.
class car{
class wheel{
}
}
There are four types of inner class.
normal inner class
Method Local Inner class
Anonymous inner class
static inner class
point ---
from static inner class ,we can only access static member of outer class.
Inside inner class we cananot declare static member .
inorder to invoke normal inner class in static area of outer class.
Outer 0=new Outer();
Outer.Inner i= O.new Inner();
inorder to invoke normal inner class in instance area of outer class.
Inner i=new Inner();
inorder to invoke normal inner class in outside of outer class.
Outer 0=new Outer();
Outer.Inner i= O.new Inner();
inside Inner class This pointer to inner class.
this.member-current inner class
outerclassname.this--outer class
for inner class applicable modifier is -- public,default,
final,abstract,strictfp,+private,protected,static
outer$inner is the name of inner class name.
inner class inside instance method then we can acess static and instance field of outer class.
10.inner class inside static method then we can access only static field of
outer class.
class outer{
int x=10;
static int y-20;
public void m1() {
int i=30;
final j=40;
class inner{
public void m2() {
// have accees x,y and j
}
}
}
}

Categories