6

I was using a static nested class in java for a particular use-case. A minimal example of the same is shown below:

public class Foo {
    static int fooInner = getInner(); // CASE 1 

    private static class StaticFoo {
        int fooInner = getInner(); // CASE 2

        public int useFooInner(){
            System.out.println(fooInner);
            //do something
        }
    }
}

The question is how is the memory allocation in Case 1 different from that in case 2? Or is it the same? What if I make the case 2 variable static too. Will the memory usage differ?

NOTE: Please do not mention that shadowing will take place. Although I have put both the variables there, but it's an "OR" case and that's why the "CASE"s.

PS: I feel that the memory usage should be the same. Since the nested class is static, it won't be created for every object and thus the instance variable fooInner (Case 2) will also be created just once. Thus, the getInner() function would run just once. But it is just at an abstract level + gut feeling. A more descriptive answer would be appreciated!

paradocslover
  • 2,932
  • 3
  • 18
  • 44
  • 1
    It doesn’t matter whether `StaticFoo` is declared `static` or not, an instance of it will only be created when evaluating a `new StaticFoo(…)` expression. Since there is none in your code, *no* instance of `StaticFoo` will ever be created, and `getInner()` will never be executed in CASE 2, not once. – Holger Jul 28 '21 at 12:15

1 Answers1

3

They are different.

From a memory allocation point of view, a static inner class is no different from a top level class. Your StaticFoo will be compiled to a class (Foo$StaticFoo.class) that is essentially independent from its parent class at runtime. At compile time, there are access checks for private members.

So, in case 1, you have a static field in a class. It will be allocated as a field on a Foo.class object on the heap. There will only be one instance per ClassLoader that loads the Foo class, which generally means just one shared instance for the whole JVM.

In case 2, you have an instance field in the Foo$StaticFoo class. On the heap, there will be space allocated (and a value assigned) for (and in) each instance of StaticFoo created. Each StaticFoo that gets created will access its own instance of that field, and since it's not final, the value of each instance can be independently changed.

If you changed StaticFoo.fooInner to be static, then it would be exactly the same as case 1.

Note: The above is true only for Java 8 and later. For earlier JVMs, that amount of memory allocated in each case still matches the description above, but static variables, as well as being singletons per ClassLoader, are also stored in a different memory pool: PermGen Space rather than the main heap. See this answer for more details.

user31601
  • 2,482
  • 1
  • 12
  • 22
  • Thanks for the answer! After reading your answer, I feel that my statement "Since the nested class is static, it won't be created for every object" was actually incorrect. In my statement, I treat static class analogous to a static instance variable inside a class, which is wrong (correct me if I am wrong). What I inferred after reading your answer was, it's just a class defined within a class and has some features like it can access private variables from the outer class, etc. Right? – paradocslover Jul 24 '21 at 08:24
  • 1
    Right. A static inner class is just a class whose _name_ is attached to the outer class, and shares its `private` namespace. This _is_ analogous to a static field or method, which is just a variable or method whose _name_ is attached to the class. In all cases there is a single class/variable/method across the whole JVM, and it is not associated with a particular _instance_ of the enclosing class. The `static` for inner classes refers to the inner _class_, not _instances_ off the inner class. – user31601 Jul 25 '21 at 09:27
  • 1
    If you remove the `static` modifier from an inner class, then each instance of the the inner class will be associated with a particular instance of the outer class, and have access to its non-static fields and methods. Instances of the inner class associated with instance `A` of the outer class cannot be assigned/substituted to variables for instances of the inner class associated with instance `B` of the outer class. It behaves exactly as if there's a separate inner _class_ for each _instance_ of the outer class. Again, this is exactly analogous to a non-static field or method. – user31601 Jul 25 '21 at 09:33
  • 2
    Also, just to note: there's no such thing as a "static instance variable". The word "instance" implies a variable associated with a particular instance of class, but the word "static" means exactly the opposite - _not_ associated with any particular instance. The correct terms are "instance field" (or just "field") and "static field" to denote variables declared outside the body of a method. – user31601 Jul 25 '21 at 09:37