Static nested class in Java, why?
Asked Answered
H

14

240

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

Homosexual answered 31/10, 2008 at 13:36 Comment(1)
javatpoint.com/java-inner-classThirtyeight
A
290

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.

Asafetida answered 31/10, 2008 at 13:47 Comment(10)
Bah, I can't seem to get an anchor link to the comment to work, but its this comment: #comment113712_253507Warlike
@matt b If a static nested class doesn't have access to the instance members of the Outer class , how does it interact with the instance members of the Outer class?Erving
I thought the primary difference was that the static class can be instantiated independent of the outer class. Am I wrong?Gorky
@SinthiaV you are not wrong, that is pretty much just a restatement of what the quoted text is saying.Asafetida
@mattb But how @Erving has noticed, the Sun page is contradictory: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class How is that possible if just a paragraph before the docs say that: Static nested classes do not have access to other members of the enclosing class Maybe they would like to say: A nested (non-static) class interacts with the instance members of its outer class (and other classes) just like any other top-level classRussia
@user3019105, there is no contradiction, and your proposed re-wording is incorrect. An inner class interacts with the instance members through an implicit reference to its enclosing class; whereas top-level classes and static inner classes do not have an "enclosing class" to reference. Top-level classes and static inner classes are mostly equivalent; inner (non-static) classes are special and rarely used.Telegu
Look at the Inner Class Example in the Java tutorial, @user3019105. How did EvenIterator get a reference to arrayOfInts? Through an implicit reference to the enclosing class. If EvenIterator were a static inner class or top-level class, arrayOfInts would need to be passed in as a method or constructor parameter.Telegu
@DavidS Thanks for the link! Yeah, I was wrong, reading my comment now I see that my rephrase was incorrect. As you said: An inner class interacts with the instance members through an implicit reference to its enclosing class, and this points out another interesting property of non-static inner classes as well as anonymous inner classes or local classes defined inside a block: they all can't have a no-arg constructor cause the compiler will implicitly prepend the arg sequence of every constructor in order to pass a reference of an instance of the enclosing class. Pretty simple.Russia
you can use static inner class to instantiate the outer class which only has private constructor. This is used in the builder pattern. You can not do the same with the inner class.Pudency
Actually non-static members of outer class can be accessed from static nested class but with the instance of outer class.Atrip
J
49

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 :)

Jaclyn answered 31/10, 2008 at 13:40 Comment(9)
I could be wrong, but that looks to me like an example of a static nested class, not an inner class. They even specify in the example that they don't have access to instance variables on the surrounding class in the nested class.Vindicate
Yup, Colin's right - C# doesn't have inner classes, it has nested classes. Mind you, a static nested class in C# isn't the same as a static nested class in Java :)Jaclyn
Nested types are one of those areas where C# got it extremely correct compared to Java. I always marvel at its semantic/logical correctness..Albion
@nawfal: Yes, barring a few niggles I'm in awe of how well the C# language has been designed (and specified).Jaclyn
@JonSkeet do you have an article or blog on what those niggles are? I would love to go thru what you find as "niggles" :)Albion
late to the party, but what is the virtue of dis-allowing classes to be packaged together, promoting encapsulation & locality of reference ? just curious about why the lack of something is a virtue - in which case the presence of that something must be a defect - what is the defect ?Ornithorhynchus
@theRiley: I'm not quite sure which part of this you're talking about. (Where was anyone talking about prohibiting nested classes entirely? Not that I'd say that's "packaging" as such.)Jaclyn
of course its packaging. i was responding to whatever virtue was being made of C# not having (non-static) inner classes. you were contending (years ago) that you saw no benefit to them. i just listed two. ymmv, but imo the ability to condense entitities which are strongly associated or mutually dependent is a pretty clear utility for any language.Ornithorhynchus
@theRiley: You can nest them fine - it's just the implicit reference from a nested instance to the enclosing instance that's not present. That can be simply achieved by doing it explicitly, at which point a lot of the complexities of inner classes in Java go away. The result is a simpler language that's just as capable IMO. (And I would say that "packaging" is what happens in terms of deployment - e.g. as a jar file, assembly or even a Maven/NuGet package. Types can be packaged together without any nesting being present at all.)Jaclyn
A
31

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.

Armoury answered 31/10, 2008 at 14:25 Comment(1)
If 'outer' class is final and therefore cannot be instantiated at all, does this argument make sense in that case? Because it having/keeping a reference to an outer class is useless, if the latter is final.Variegation
P
17

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

Pudency answered 26/10, 2016 at 16:25 Comment(1)
We can call a private constructor of Outerclass from Non static Inner class.Abstinence
P
11

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;
    }
}
Pliocene answered 16/12, 2013 at 10:31 Comment(1)
static nested class is just like any other outer class, as it doesn't have access to outer class members -- this is incorrect. A Static Nested Class (SNC) has complete access to ALL class members of enclosing class. It cannot access "instance members". See Inner Class and Nested Static Class Example.Upali
E
10

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.

Easterling answered 31/10, 2008 at 13:52 Comment(0)
G
7

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.

Goya answered 21/11, 2013 at 19:9 Comment(0)
E
4

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)

Eldwun answered 31/10, 2008 at 13:58 Comment(1)
your StaticInnerClass is not, in fact, a static nested/inner class. it is a top-level static class.Ornithorhynchus
B
2

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.

Bezoar answered 31/10, 2008 at 13:46 Comment(0)
R
2
  1. JVM knows no nested classes. Nesting is just syntactic sugar.

    Below images shows Java file:

    enter image description here

    Below images show class files representation of the java file :

    enter image description here

    Notice that 2 class files are generated, one for parent and another for nested class.

  2. 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

  3. 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;
    }
    }
    
  4. 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
    }
    
  5. More details here.

Recipient answered 18/9, 2020 at 5:53 Comment(0)
L
1

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.

Linchpin answered 24/11, 2011 at 13:26 Comment(2)
'static inner' is a contradiction in terms.Evieevil
@EJP, sheesh... people really get-off by pointing this out any time someone mentions “static inner classes”...Danilodanio
C
0

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.

Converse answered 31/10, 2008 at 13:46 Comment(2)
An innner class isn't 'part of an instance of the enclosing class' either.Evieevil
an inner class is existentially dependent upon the enclosing class, and has intimate access to the members of the enclosing class, so it actually is a part of the enclosing class. in fact, it is a member.Ornithorhynchus
R
0

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.

Rybinsk answered 22/10, 2016 at 13:13 Comment(0)
N
-1

Adavantage of inner class--

  1. one time use
  2. supports and improves encapsulation
  3. readibility
  4. private field access

Without existing of outer class inner class will not exist.

class car{
    class wheel{

    }
}

There are four types of inner class.

  1. normal inner class
  2. Method Local Inner class
  3. Anonymous inner class
  4. static inner class

point ---

  1. from static inner class ,we can only access static member of outer class.
  2. Inside inner class we cananot declare static member .
  3. inorder to invoke normal inner class in static area of outer class.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  4. inorder to invoke normal inner class in instance area of outer class.

    Inner i=new Inner();

  5. inorder to invoke normal inner class in outside of outer class.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  6. inside Inner class This pointer to inner class.

    this.member-current inner class outerclassname.this--outer class

  7. for inner class applicable modifier is -- public,default,

    final,abstract,strictfp,+private,protected,static

  8. outer$inner is the name of inner class name.

  9. 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
            }
        }
    }
}
Nitpicking answered 1/3, 2016 at 7:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.