最近,我遇到了一篇关于Android中内存优化的文章,但我认为我的问题更多的是一种通用Java类型。我找不到这方面的任何信息,所以如果你能给我一个好的阅读资源,我将不胜感激。
我说的这篇文章可以找到这里。
我的问题涉及以下两个片段:
非最佳版本:
List<Chunk> mTempChunks = new ArrayList<Chunk>();
for (int i = 0; i<10000; i++){
mTempChunks.add(new Chunk(i));
}
for (int i = 0; i<mTempChunks.size(); i++){
Chunk c = mTempChunks.get(i);
Log.d(TAG,"Chunk data: " + c.getValue());
}优化版本:
Chunk c;
int length = mTempChunks.size();
for (int i = 0; i<length; i++){
c = mTempChunks.get(i);
Log.d(TAG,"Chunk data: " + c.getValue());
}本文还包含以下行(与第一个片段相关):
在上面代码片段的第二个循环中,我们为循环的每一次迭代创建一个新的块对象。因此,它实际上将创建10000个类型为“块”的对象,并占用大量内存。
我正在努力理解的是,为什么提到一个新的对象创建,因为我只能看到堆中已经存在的对象的引用的创建。我知道引用本身要花费4-8字节,这取决于系统,但在这种情况下,它们很快就超出了范围,除此之外,我没有看到任何额外的开销。
也许是创建了一个对现有对象的引用,当大量的对象被认为是昂贵的?
请告诉我这里遗漏了什么,以及这两个片段在内存消耗方面的真正区别是什么。
谢谢。
发布于 2015-04-02 20:33:22
有两个不同之处:
非最佳的:
i < mTempChunks.size()Chunk c = mTempChunks.get(i);最佳:
i < lengthc = mTempChunks.get(i);在非最优代码中,为循环的每一次迭代调用size()方法,并创建对Chunk对象的新引用。在最优代码中,避免了重复调用size()的开销,并回收了相同的引用。
然而,这篇文章的作者认为在第二个非最优循环中创建了10000个临时对象,这似乎是错误的。当然,创建了10000个temp对象,但是在第一个循环中,而不是在第二个循环中,没有办法避免这种情况。在第二个非最优循环中,创建了10000个引用.因此,在某种程度上,它并不是最优的,尽管作者把树误认为是森林。
进一步参考资料:
1. 避免创建不必要的对象.
2. 使用增强的循环语法.
编辑:
有人指控我是个骗子。对于那些说呼叫size()没有开销的人,我只能引用官方文档。
3. 避免内部获取器/设置器.
编辑2:
在我的回答中,我最初犯了一个错误,我说引用的内存是在堆栈的编译时分配的。我现在意识到,这个说法是错误的;这实际上是C++中的工作方式,而不是Java。Java的世界是颠倒的:虽然引用的内存确实在堆栈上分配,但在Java中甚至在运行时也是如此。心神不宁!
参考资料:
2. 在堆栈中还是堆中分配变量引用?.
3. Java虚拟机框架的结构.
https://stackoverflow.com/questions/29421287
复制相似问题