繁体   English   中英

`new`关键字做什么

[英]What does the `new` keyword do

我正在线上学习Java教程,试图学习这门语言,并且它在使用数组的两种语义之间蹦蹦跳跳。

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

和:

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

教程从未真正提到为什么它在两者之间来回切换,所以我对这个主题进行了一些搜索。 我目前的理解是new运算符正在创建一个“longs数组”类型的对象。 明白的是为什么我想要那个,那有什么后果?

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

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

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

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

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

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

没有数组不是对象,所以没有。 ,但是,这不会对原始阵列工作方式。 采用Object[]方法不会先接受long[]而不先将其转换为Long[] 这是由于Java 5及更高版本中的自动装箱的一些实现细节。

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

任何用new分配的东西最终都必须被垃圾收集,所以在做任何事情时通常都不会这样做? 否。但是,请注意,在C / C ++,分配使用数组malloc / new意味着你也有free / delete []它,这是你没有用Java做的,因为它会收回该阵列为你。

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

编辑:承诺的一些参考:

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

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

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

所有数组都是对象。 期。

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

往上看。

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

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

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

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

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

来自JLS#Chapter 10. Arrays

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

10.3. Array Creation 10.3. Array Creation

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

15.10. Array Creation Expressions 15.10. Array Creation Expressions

数组创建表达式创建一个对象,该对象是一个新数组,其元素的类型是PrimitiveTypeClassOrInterfaceType指定的类型。

10.6. Array Initializers 10.6. Array Initializers

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

两者都初始化数组,差异是第二个用一些值初始化。

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

以下两个代码片段在编译级别中是等于的。 我写了一个Demo类:

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

}

长期结果[] = new long [] {1,2,3}; 结果很长[] = {1,2,3}; 也完全一样。

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

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

在这两种情况下,您都会创建一个对

在第一个版本中:

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] :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM