16

我正在在线关注 Java 教程,尝试学习该语言,它在使用数组的两种语义之间来回切换。

long results[] = new long[3];
results[0] = 1;
results[1] = 2;
results[2] = 3;

和:

long results[] = {1, 2, 3};

该教程从未真正提到为什么它在两者之间来回切换,所以我搜索了一些关于该主题的内容。我目前的理解是new操作员正在创建一个“长数组”类型的对象。我明白我为什么要那样做,这样做的后果是什么?

  • 除非它是“数组对象”,否则是否有某些特定于“数组”的方法不适用于数组?
  • 有什么我不能用普通数组做的“数组对象”做的吗?
  • Java VM 是否必须对使用运算符初始化的对象进行清理,new而这通常不需要这样做?

我来自 C,所以我的 Java 术语在这里可能不正确,所以如果有什么不能理解的,请要求澄清。

4

9 回答 9

13

在Java中,所有的数组和对象都分配在堆上,所以从某种意义上说,所有的数组都是“数组对象”。在 Java 中,唯一在堆栈上分配的东西是对象引用和原语。其他一切都是在堆中定义和分配的对象,包括数组,无论您使用哪种语法来声明它。(您的两个示例在最终结果中是等效的,请参阅JLS §10.3及其链接部分,了解有关如何实际分配和分配每个示例的更多信息。)

这与 C/C++ 相反,在 C/C++ 中,您可以显式控制堆栈和堆分配。

请注意,Java 在短期对象分配/释放方面非常快。由于其基于生成的垃圾收集器,它非常高效。所以回答你的问题:

除非它是“数组对象”,否则是否有某些特定于“数组”的方法不适用于数组?有什么我不能用普通数组做的“数组对象”做的吗?

没有数组不是对象这样的东西,所以没有。但是,有些方法不适用于原始数组。采用 a 的方法如果不先将Object[]a 转换为 ,则不会接受它。这是由于 Java 5 及更高版本中自动装箱的一些实现细节。long[]Long[]

Java VM 是否必须对使用运算符初始化的对象进行清理,new而这通常不需要这样做?

任何分配的东西new最终都必须被垃圾收集,所以就做它通常不会做的事情而言?malloc不。但是,请注意,在 C/C++ 中,使用/分配数组new意味着您还必须free/delete []它,这是您不必在 Java 中执行的操作,因为它会为您回收数组。

请注意,如果您long[]在方法中声明,并且您从未将其存储在方法之外的某个引用中,则它将在方法调用结束时自动标记为垃圾回收。垃圾收集器将等待回收其空间,直到它需要它,但您不必自己通过delete [](或delete对象的析构函数)进行任何回收。

编辑:承诺的一些参考资料:

于 2012-12-18T05:01:54.643 回答
7

Java 中的new关键字创建一个新对象。在这种情况下,它正在创建一个数组......这是一个对象。

这两种形式是等价的。第二个只是第一个的方便简写。它是语法糖

除非它是“数组对象”,否则是否有某些特定于“数组”的方法不适用于数组?

所有数组都是对象。时期。

有什么我不能用普通数组做的“数组对象”做的吗?

看上面。

Java VM 是否必须对使用 new 运算符初始化的对象进行清理,而这通常不需要这样做?

不。就 JVM 而言,以不同方式创建的对象之间没有区别。

于 2012-12-18T05:00:41.977 回答
5

两者在创建的数组的行为方面是相同的。所有数组在技术上都是java中的对象;这些只是初始化它们的两种不同方式。也可以像这样将两者结合起来:

long[] results = new long[]{1,2,3};
于 2012-12-18T05:01:01.203 回答
3

两者都是一样的。第二个选项是隐式创建数组对象,这只是为了方便用户。

于 2012-12-18T05:00:53.153 回答
3

JLS#Chapter 10. Arrays

在 Java 编程语言中,数组是对象(第 4.3.1 节),是动态创建的,并且可以分配给 Object 类型的变量(第 4.3.2 节)。Object 类的所有方法都可以在数组上调用。

10.3. Array Creation

数组由数组创建表达式(§15.10)或数组初始值设定项(§10.6)创建

15.10. Array Creation Expressions

数组创建表达式创建一个对象,该对象是一个新数组,其元素属于PrimitiveTypeor指定的类型ClassOrInterfaceType

10.6. Array Initializers

数组初始值设定项可以在声明中指定(第 8.3 节、第 9.3 节、第 14.4 节),或作为数组创建表达式的一部分(第 15.10 节)来创建数组并提供一些初始值。

两者都初始化数组,区别在于第二个用一些值初始化。

于 2012-12-18T05:01:33.550 回答
1

以下两个代码片段在编译级别上是相等的。我写了一个演示类,如:

public class NewArray {
    public static void main(String[] args) {
        long results[] = new long[3];
    }
}

public class NewArray {
    public static void main(String[] args) {
        long results[] = {0,0,0};
    }
}

'javap -c NewArray' 的输出完全相同:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_3
   1:   newarray long
   3:   astore_1
   4:   return

}

长结果 [] = 新长 []{1,2,3}; 和长结果[] = {1,2,3}; 也完全一样。

所以,虽然有时你没有使用新的关键字,但编译会认为它们是平等的。

于 2012-12-18T05:39:48.673 回答
1

您展示的两种创建方式是等效的。两者都是“数组对象” - 请记住,Java 中的所有内容(除了基本的数字类型,如int,double等)都是对象。第二个只是第一个的简写,就像 C 对堆栈分配的整数数组有类似的简写一样。

于 2012-12-18T05:01:34.703 回答
1

'new' 关键字创建一个数组。现在,根据数组的数据类型,其中的值会有所不同。如果您将数组声明为整数并使用“new”关键字,那么它将包含值 0,除非您更改其中的值。使用字符串,它将包含值“null”。在每一个空间。

于 2016-11-14T14:30:36.640 回答
0

在这两种情况下,您都创建了一个对象。

在第一个版本中:

long results[] = new long[3];
results[0] = 1;
results[1] = 2;
results[2] = 3;

您在第一行中说数组大小为 3。然后将值放入数组中。

在第二个版本中:

long results[] = {1, 2, 3};

您创建相同的数组并在同一行中对其进行初始化。Java 计算,您提供了 3 个参数并在new long[3]没有您的帮助的情况下生成 :)

于 2012-12-19T20:33:21.420 回答