7

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!

1
  • 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. Commented Jul 28, 2021 at 12:15

1 Answer 1

3
+50

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.

Sign up to request clarification or add additional context in comments.

4 Comments

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.