此查询的目的是比较Java和C ++的一个方面,它与“new”运算符有关。
现在,我知道在C ++中有两种创建对象的方法;有或没有“新”运算符。如果没有该运算符,则不会在堆区域中分配空间,而在存在时,会在堆区域中分配空间。
Java怎么样?我注意到“new”运算符用于创建每个对象。甚至数组都是使用“new”运算符创建的。这是否意味着在Java中只存在一个对象存在的位置 - 即堆区域?
感谢。
答案 0 :(得分:6)
是的,new运算符总是为堆上的对象分配内存。与C ++不同,Java中的对象无法在堆栈中创建。
答案 1 :(得分:4)
本地基元类型和本地引用到对象类型都占用“堆栈”内存,就像它们作为参数传递给方法时一样。
所有对象本身都存在于“堆”中。
答案 2 :(得分:2)
从应用程序和应用程序员 2 的角度来看,所有Java对象(即所有带引用的东西)都在堆 1 中分配。 Java不支持在堆栈上显式分配对象。对象引用既可以存储在堆节点(即类或实例字段)和堆栈帧(即局部变量等)中。
事实上,有一些方法可以用Java创建第一类Java对象不涉及使用new
关键字。
{ ... }
数组初始值设定项语法可以在没有new
关键字的数组声明中使用。
字符串文字涉及创建String对象(在类加载时)。
装箱转换(通常)会创建一个新的包装器对象,而不会显式调用new
或方法。
反射newInstance
和类似方法创建没有明确new
的对象。
简而言之,Java序列化的实现使用Unsafe
类中的特殊方法来创建对象而不执行任何声明的构造函数。
您还可以使用JNI / JNA apis在本机代码中创建Java对象。
(有一个强有力的论据,即最后两个是“非Java”,但无论如何它们都值得一提。而String文字和自动装箱案例涉及使用new
的Java代码。)
1 - 可以有多个堆,但这对应用程序是透明的。
2 - 最新的Hotspot JVM具有实验性的“逃逸分析”功能,可以确定对象是否从创建它们的上下文中“逃脱”。可以在堆栈上安全地分配无法转义的对象。再一次,这种优化对应用程序是透明的。
答案 3 :(得分:0)
在Java中,所有对象都在Heap上动态分配。这与C ++不同,在C ++中,可以在Stack或Heap上为对象分配内存。在C ++中,当我们使用new()
分配abject时,abject在Heap上分配,否则在Stack上分配,如果不是全局或静态的。
在Java中,当我们只声明类类型的变量时,只创建一个引用(不为该对象分配内存)。要为对象分配内存,我们必须使用new()。所以对象总是在堆上分配内存。
示例1:给出编译错误。
class Test {
void show() {
System.out.println("Test::show() called");
}
}
public class Main {
public static void main(String[] args) {
Test t;
t.show(); // Error here because t is not initialed
}
示例2 :使用new()
分配内存使上述程序正常工作。
class Test {
void show() {
System.out.println("Test::show() called");
}
}
public class Main {
public static void main(String[] args) {
Test t = new Test(); //all objects are dynamically allocated
t.show(); // No error
}
}