【问题标题】:what requires more memory - nested class / separate class什么需要更多内存 - 嵌套类/单独类
【发布时间】:2013-11-16 02:52:59
【问题描述】:

什么会占用更多内存:

  1. 创建嵌套类
  2. 创建一个单独的类

这不是一个面向对象/设计相关的问题,我只是想知道并想知道答案。

提前谢谢你。

举例说明:

情况一

汽车.java

public class Car {

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

// Methods doing operations on Door

}

Door.java

public class Door{

}

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

情况 2

汽车.java

public class Car {


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

// Methods doing operations on Door

public class Door {

}

}

如果Door 上的所有操作都由Car 类完成,则上述哪种情况更高效。没有其他类访问Door

【问题讨论】:

  • 你到底是什么意思?
  • 创建一个两者的示例,检查使用的堆空间量,并在此处返回您的示例和结果。
  • 嵌套类可能需要更多字节,因为必须维护两个类之间的关系。
  • 如果DoorCarstatic 嵌套类,则Door 对象不会比Door 是另一个顶级类占用更多内存。
  • @user590849:更重要的是,你为什么要问这个问题?您提出问题的事实是一个危险信号,表明您提出了错误的问题。

标签: java class nested-class


【解决方案1】:

我快速汇总的这个测试估计了单独、嵌套和静态嵌套类的大小大致相同:

// 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();
    }

}

我的输出是:

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

没有成员字段(也没有分配的字节数组),输出是:

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

这与我们的预期一致(例如,参见 https://stackoverflow.com/a/258150/616460)。

它通过在每轮实例化后测量可用内存的差异来工作。 freeMemory() 在后台等待 GC 稳定下来。

一个非静态嵌套类显示了一些额外的开销,但有一些对齐(例如删除它们的成员,或添加不是像字节数组这样的单独对象的较小的原始成员)。

当然,我们从中没有学到任何有用的东西。真正的问题是,你为什么要问这个?您提出的问题是一个危险信号,表明您提出了错误的问题。

【讨论】:

  • 我为什么要问这个?好吧,就像我在问题中所说的那样 - 我只是想知道。
  • 请参阅stackoverflow.com/questions/52353/…,了解一些专门测量对象大小的好方法(仪器包将为您提供比此测试更详细的信息)。
  • 嵌套稍大,因为它包含对包含类的引用。
  • 非常感谢你做这个基准测试。我一直在想这个问题。
【解决方案2】:
  • 据我所知,原始值始终位于堆栈中。 引用对象被创建并存在于堆中,而每个引用对象的 参考变量像其他的一样存在于堆栈中 原语。
  • 执行方法是一种执行方法,规则将 总是适用于事物的生存和死亡(即堆或堆栈)。 所以,为了纠正你的措辞......你应该说“记忆如何 对于分配的变量以及某些方法的位置..."
  • 内部类只是被内部化的常规类。所以,像 所有其他很酷的类,它们只是对象的蓝图 你最终会创建(在堆上),然后你才会 由于您的内部课程而使用内存。
  • 然而,从技术上讲,有一个实际的“类对象”浮动 在你的内部类的某个地方,所以如果你有静态成员 那里(变量)会导致一些内存使用。
  • 将封闭类及其内部类视为单向类 协会。孩子需要知道他的父母是谁,但是 父母不在乎(释义)。
  • 如果您确实需要获取内部类实例的数据,您可以 可以将其存储在封闭的常规 ol' 实例变量中 像往常一样对其进行类和调用方法。

如果不是很抱歉浪费您的时间,我想这会有所帮助。

【讨论】:

  • 次要更正:局部变量位于堆栈上(原语和引用,当然不是引用指向的实际对象)。当通过new 构造对象时,非静态原始字段最终会出现在堆上并且是对象占用空间的一部分。我相信静态原始/引用字段也在堆上,但我不记得我的头顶。
猜你喜欢
  • 2020-01-12
  • 2010-11-08
  • 1970-01-01
  • 2012-10-26
  • 2017-12-15
  • 1970-01-01
  • 2013-01-04
  • 2017-09-14
  • 1970-01-01
相关资源
最近更新 更多