2

What takes up more memory:

  1. Creating a nested class
  2. Creating a separate class

This is not a OO/design related question, I was just wondering and wanted to know the answer.

Thank you in advance.

EXPLANATION WITH EXAMPLE :

SITUATION One

Car.java

public class Car {

ArrayList< Door > = new ArrayList< Door >()

// Methods doing operations on Door

}

Door.java

public class Door{

}

=========================== OR ===========================

SITUATION 2

Cars.java

public class Car {


ArrayList< Door > = new ArrayList< Door > ()

// Methods doing operations on Door

public class Door {

}

}

Which of the above situations is more MEMORY efficient if all the operations on Door are done by class Car. No other class accesses Door.

Steve P.
  • 14,489
  • 8
  • 42
  • 72
user590849
  • 11,655
  • 27
  • 84
  • 125
  • What exactly do you mean by that? – Steve P. Nov 16 '13 at 02:56
  • Create an example of both, examine the amount of heap space used, and post back here with your example and the results. – Jason C Nov 16 '13 at 02:59
  • nested class probably needs a few more bytes, since the relationship between the two classes has to be maintained. – ZhongYu Nov 16 '13 at 03:04
  • if `Door` is a *static* nested class of `Car`, `Door` objects won't take more memory than if `Door` were another top level class. – ZhongYu Nov 16 '13 at 03:23
  • @user590849: More importantly, why are you asking this question? The fact that you are asking it is a red flag suggesting that you are asking the wrong questions. – Jason C Nov 16 '13 at 03:27

2 Answers2

2

This test I threw together quickly estimates roughly the same size for separate, nested, and static nested classes:

// separate class
class Separate { byte[] x = new byte[1000]; }

public class Test1 {

    // non-static nested
    class Nested { byte[] x = new byte[1000]; }

    // static nested
    static class StaticNested { byte[] x = new byte[1000]; }

    static long getFreeMemory () {
        // waits for free memory measurement to stabilize
        long init = Runtime.getRuntime().freeMemory(), init2;
        int count = 0;
        do {
            System.out.println("waiting..." + init);
            System.gc();
            try { Thread.sleep(250); } catch (Exception x) { }
            init2 = init;
            init = Runtime.getRuntime().freeMemory();
            if (init == init2) ++ count; else count = 0;
        } while (count < 5);
        System.out.println("ok..." + init);
        return init;
    }

    Test1 () {

        Object[] s = new Object[10000];
        Object[] n = new Object[10000];
        Object[] t = new Object[10000];

        long init = getFreeMemory();

        for (int j = 0; j < 10000; ++ j)
            s[j] = new Separate();

        long afters = getFreeMemory();

        for (int j = 0; j < 10000; ++ j)
            n[j] = new Nested();

        long aftersn = getFreeMemory();

        for (int j = 0; j < 10000; ++ j)
            t[j] = new StaticNested();

        long aftersnt = getFreeMemory();

        System.out.println("separate:      " + -(afters - init) + " each=" + -(afters - init) / 10000);
        System.out.println("nested:        " + -(aftersn - afters) + " each=" + -(aftersn - afters) / 10000);
        System.out.println("static nested: " + -(aftersnt - aftersn) + " each=" + -(aftersnt - aftersn) / 10000);

    }

    public static void main (String[] args) {
        new Test1();
    }

}

Output for me is:

separate:      10320000 each=1032
nested:        10400000 each=1040
static nested: 10320000 each=1032

With no member fields (and no allocated byte arrays), output is:

separate:      160000 each=16
nested:        160000 each=16
static nested: 160000 each=16

This agrees with what we'd expect (see https://stackoverflow.com/a/258150/616460 for example).

It works by measuring difference in free memory after each round of instantiations. freeMemory() waits for the GC to stabilize in the background.

A non-static nested class shows a bit of extra overhead but there is some alignment going on (e.g. remove their members, or add smaller primitive members that aren't separate objects like the byte array).

Of course, we learn nothing useful from this. The real question is, why are you asking this? The fact that you are asking it is a red flag suggesting that you are asking the wrong questions.

Community
  • 1
  • 1
Jason C
  • 38,729
  • 14
  • 126
  • 182
  • Why am I asking this ? Well, like I said in the question - I was just wondering. – user590849 Nov 16 '13 at 03:32
  • See http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object/20014332 for some good ways to specifically measure the size of an object (the instrumentation package will give you more detailed information than this test). – Jason C Nov 16 '13 at 03:38
  • Nested is slightly larger because it contains a reference to the containing class. – brettw Nov 16 '13 at 09:34
  • Thank you so much for doing this bench marking. I've been wondering about this for a while. – Leo Ufimtsev Feb 09 '17 at 17:12
0
  • As of my knowledge, primitive values are always located on the stack. Reference objects are created and live on the heap, while each's reference variable lives on the stack like the rest of the primitives.
  • A method of execution is a method of execution and the rules will always apply concerning where things live and die (ie heap or stack). So, to correct you wording ... you should have said "how is memory for variables allocated and where for some methods..."
  • Inner classes are just regular classes that are inner'ed. So, like all the other cool classes, they're just blueprints for objects which you will eventually create (on the heap) and only then will you be using memory due to your inner class.
  • Technically, however, there is an actual "class object" floating around somewhere for your inner class so if you had static members in there (variables) it would incur some memory usage.
  • Think of an enclosing class and its inner class as a uni-directional association. The child needs to know who its parent is, but the parent don't care (paraphrase).
  • If you really needed to get at an inner class instance's data, you could store it in a regular ol' instance variable in the enclosing class and invoke methods on it just as you normally would.

I guess this helps a little if not sorry for wasting your time.

Vinith
  • 1,264
  • 14
  • 25
  • Minor correction: Local variables are located on the stack (both primitives and references but not, of course, actual objects pointed to by references). Non-static primitive fields would end up on the heap and are part of the footprint of the object when it is constructed via `new`. I *believe* static primitive/reference fields are on the heap as well but I do not recall off the top of my head. – Jason C Nov 16 '13 at 03:40