6

此查询的目的是比较 Java 和 C++ 的一个方面,这与“new”运算符有关。

现在,我知道在 C++ 中有两种创建对象的方法;有或没有“新”运算符。如果没有该运算符,则不会在堆区域中分配空间,而在存在该运算符时,会在堆区域中分配空间。

爪哇呢?我注意到“new”运算符用于创建每个对象。甚至数组也是使用“new”运算符创建的。这是否意味着在 Java 中对象只有一个存在的地方——即堆区域?

谢谢。

4

4 回答 4

6

是的,new 运算符总是为堆上的对象分配内存。与 C++ 不同,Java 中的对象不能在堆栈上创建。

于 2012-09-16T05:42:54.327 回答
4

本地原始类型和对对象类型的本地引用都占用“堆栈”内存,就像它们作为参数传递给方法时一样。

所有对象本身都存在于一个“堆”的等价物中。

于 2012-09-16T05:41:07.120 回答
2

从应用程序和应用程序程序员2的角度来看,所有 Java 对象(即所有具有引用的事物)都分配在堆1中。Java 不支持在堆栈上显式分配对象。对象引用可以存储在堆节点(即类或实例字段)和堆栈帧(即局部变量等)中。

事实上,有几种方法可以在涉及使用new关键字的 Java 中创建一流的 Java 对象。

  • { ... }数组初始值设定项语法可以在没有关键字的数组声明中使用new

  • 字符串文字涉及创建字符串对象(在类加载时)。

  • 装箱转换将(通常)创建一个新的包装器对象,而无需显式new或方法调用。

  • 反射newInstance和类似方法创建没有显式new.

  • 在底层,Java 序列化的实现使用Unsafe类中的一种特殊方法来创建对象,而无需执行任何已声明的构造函数。

  • 您还可以使用 JNI / JNA api 在本机代码中创建 Java 对象。

(有一个强烈的论点是最后两个“不是 Java”,但无论如何它们都值得一提。字符串文字和自动装箱案例涉及在底层使用new的 Java 代码。)


1 - 可以有多个堆,尽管这对应用程序是透明的。

2 - 最新的 Hotspot JVM 具有实验性的“逃逸分析”功能,可确定对象是否从创建它们的上下文中“逃逸”。不会逃逸的对象可以安全地分配到堆栈上。再一次,这种优化对应用程序是透明的。

于 2012-09-16T09:59:12.880 回答
0

在 Java 中,所有对象都在 Heap 上动态分配。这与 C++ 中的对象可以在堆栈或堆上分配内存不同。在 C++ 中,当我们使用 分配 abject 时new(),abject 分配在堆上,否则如果不是全局或静态的,则分配在堆栈上。

在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 
    }
}
于 2016-10-04T12:53:00.400 回答