从我的研究中,我知道你可以使用static final
修饰符在Java中获得几乎类似C的常量值。即static final int my_const_int = 5;
。
通过实验,我发现您可以以相同的方式创建常量对象,但需要使用new
关键字,即static final Color c = new Color(100,100,100,255);
我的问题是:使用此方法将在运行时在堆上分配Color对象,在运行时在堆栈上分配(Java甚至使用堆栈?),或者在编译时以某种方式评估它是时候减少内存占用了吗?
我是最近转换成的C程序员,所以虽然我对内存的了解相当不错,但我对Java如何使用它几乎一无所知。任何见解将不胜感激。
答案 0 :(得分:3)
所有对象都存储在堆上,甚至是static final
个。就编译器所知,该对象可能是可变的。
只有基元和引用存储在堆栈中。
在相关的说明中,编译器将内联使用它们的原始常量。
答案 1 :(得分:1)
所有对象都在Java中分配在堆上。您在堆栈上进行变量分配的唯一时间是本地声明的基元和本地声明的对堆上对象的引用(想想"指针",但没有指针算术,解除引用等)。
另外值得注意的是,由于数组是对象,它们也在堆中分配,并且在线程堆栈中保持对指针的引用,即使它是像{{1这样的原始数组}}
编辑:感谢Marko进行此次修改。 Hotspot JVM(以及可能是其他人)可以根据对象引用是否可以" escape"来执行优化。方法或堆栈框架。如果对象的引用没有在堆栈帧之间传递(即它被发布到其他线程),也没有传递给父堆栈帧(即由方法返回),那么该对象被认为是" unescapable&# 34;并且在堆栈框架内部分配,类似于在C ++中在堆栈上分配对象的方式。 Here's the reference
答案 2 :(得分:1)
从我从C切换到Java时:
第一个技巧是忘记你对内存的所有了解,特别是关于存储常量的最有效方法。 Java非常简单,你不需要为此烦恼。第二个诀窍就是学会故意做所有你在C中都不敢做的简单事情。创造对象并忘记它们:不要担心谁有指针,不要# 39;如果他们已经被释放,请不要担心,不要担心你在百万周期循环中反复分配和释放空间。
关于Java内存的三件事:
你无法加速它。 Java将每个东西放在一个单独分配的内存中,并用引用跟踪它。在C中,您可以在一个连续的内存块中排列多组嵌套结构。无论你做什么,在Java中同样的事情将是一组指针("引用")到其他内存块,其中许多仍然是更多的指针集。接受它。
你不能放慢速度。 Java优化器会做任何事情来让你的代码运行得更快,JVM优化器会在你的代码运行时完成它。将对象放在堆栈上(如其他地方所述)是典型的。
(这不是你通常需要考虑的事情,但它可以做一些奇怪的事情来进行基准测试.JVM可以巧妙地注意到,在循环运行时,你是实际上并没有查看你正在填充的百万数字数组中的5个以上的元素,并且使循环摇摆,所以它只运行5次以填充这5个元素。)
最重要的一个:
你不能搞砸了!如果你有一个带有(非空)引用的变量,那就好了。对象就在那里。它与参考设置时的对象相同。最令人惊讶的是,当您停止使用某些东西时 - 而仅当您停止使用它时 - 空间被释放。将一个引用取消为数百万个对象的广泛图表和...噗! 所有都没了!你可以在不使用更多内存的情况下构建同样大的东西。 Java的一个关键(也许是 键)就是为了它的所有价值。
(免责声明:大型数组和使用它们的东西--ArrayList,HashTable - 可以惹恼垃圾收集器并导致它需要更多的内存。但是后来担心这一点。 )
一般情况下,请使用" static"等词语。和"最终"控制程序的功能,而不是试图提高速度或内存使用率。指定算法是你的工作。 Java的工作是快速运行它。
(再次免责声明:如果你保留太多太大的对象,你将耗尽内存。这样做会在不知不觉中产生一种Java"内存泄漏" - 与C内存泄漏有很大不同。但是如果要减少内存使用量,则必须通过重新设计类来实现,而不是重新设计数据原语在类中的存储方式。)