用Java内联声明数组是否更快(或更好)?
考虑以下两个几乎相等的方法调用。注意字节数组在这两个节点上的声明和分配方式用Java内联声明数组是否更快(或更好)?,java,arrays,inline,Java,Arrays,Inline,考虑以下两个几乎相等的方法调用。注意字节数组在这两个节点上的声明和分配方式 void Method1() { byte [] bytearray = new byte[16]; /* some code */ } void Method2() { byte [] bytearray = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* some code */ } 在这两种情况下,假设Method1和Method2返回时
void Method1()
{
byte [] bytearray = new byte[16];
/* some code */
}
void Method2()
{
byte [] bytearray = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
/* some code */
}
在这两种情况下,假设Method1和Method2返回时,“bytearray”是垃圾收集的候选对象,因为操纵bytearray变量的代码都不会持有超过方法本身结尾的引用
方法2是否通过避免调用“new”而运行得更快(或不同)?或者上述两种实现是等效的?在这两种情况下,Java编译器或运行时是否可以进行优化,以避免为这个短暂的临时缓冲区命中内存分配器的开销?这两种方法完全等效。但是,第二种方法更为详细,对于较长的数组或者如果您想修改数组长度,则不太方便。它们是相同的
new
关键字创建一个对象。但在Java中,数组是。。物体。见:
在Java编程语言中,数组是对象(§4.3.1),是
动态创建,并可分配给Object类型的变量
(§4.3.2). 类对象的所有方法都可以在数组上调用。..
数组是由数组创建表达式或数组初始值设定项创建的
这两种方法没有区别。这只是语法上的问题。最好使用第一种样式 在第二种风格中,我试图找到一个非0。它保证了更无错误,因此可读性更好
这个速记有很好的理由存在两者都是相同的…因为它们都将在堆上占据相同的空间…字节码将是很好地研究它的选项两者都是相同的,但我不推荐第二个,因为读写和调试都很困难。想象一下,你会发现:
byte [] bytearray = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
你能告诉我数组的大小是否正确吗?是的,但想象一下:
byte [] bytearray = new byte[25];
这要容易得多
想象一下,数组长度是100 哪种形式最快?取决于JIT-它们可能是等价的。如果有的话,很少有程序会注意到差异 哪种形式最好?几乎总是让程序更具可读性的形式 但是,不管我们是否注意到,有什么实际的区别吗?让我们看看
class ArrayTest {
public int[] withNew() {
int[] arr = new int[4];
return arr;
}
public int[] withInitializer() {
int[] arr = {0, 0, 0, 0};
return arr;
}
}
我们使用javap-carrayTest
来分解它:
Compiled from "ArrayTest.java"
class ArrayTest {
ArrayTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public int[] withNew();
Code:
0: iconst_4
1: newarray int
3: astore_1
4: aload_1
5: areturn
public int[] withInitializer();
Code:
0: iconst_4
1: newarray int
3: dup
4: iconst_0
5: iconst_0
6: iastore
7: dup
8: iconst_1
9: iconst_0
10: iastore
11: dup
12: iconst_2
13: iconst_0
14: iastore
15: dup
16: iconst_3
17: iconst_0
18: iastore
19: astore_1
20: aload_1
21: areturn
}
尽管这会编译成另一组字节码,它们基本相同,但并不完全相同:
public int[] withNewAndSettingExplicitly();
Code:
0: iconst_4
1: newarray int
3: astore_1
4: aload_1
5: iconst_0
6: iconst_0
7: iastore
8: aload_1
9: iconst_1
10: iconst_0
11: iastore
12: aload_1
13: iconst_2
14: iconst_0
15: iastore
16: aload_1
17: iconst_3
18: iconst_0
19: iastore
20: aload_1
21: areturn
因此,这个故事的寓意是:如果你想让所有元素都设置为0
,你就可以用new int[size]
生成更少的字节码(这可能更快,也可能更快),但你还必须输入更少的字节码(这是一个巨大的胜利)。如果要在分配数组时直接设置数组中的值,请使用代码中看起来最好的值,因为生成的代码将与您选择的任何形式几乎相同
现在,回答您的实际问题:
方法2是否通过避免调用“new”而运行得更快(或不同)
正如我们所看到的,new
隐藏在初始化器语法后面(查找newarray
op代码)。顺便说一句,JVM中的分配非常便宜(分代垃圾收集器具有令人愉快的副作用)
或者上述两种实现是等效的
正如我们所看到的——不完全如此,但不太可能有人会注意到其中的差异
在这两种情况下,Java编译器或运行时是否可以进行优化,以避免为这个短暂的临时缓冲区命中内存分配器的开销
再说一次-分配很便宜,所以不要担心。然而,最近的JVM有一个称为的小特性,这可能导致数组被堆栈分配,而不是堆分配 事实上,它们并不生成相同的字节码,尽管它们在功能上是等价的。
public int[] withNewAndSettingExplicitly();
Code:
0: iconst_4
1: newarray int
3: astore_1
4: aload_1
5: iconst_0
6: iconst_0
7: iastore
8: aload_1
9: iconst_1
10: iconst_0
11: iastore
12: aload_1
13: iconst_2
14: iconst_0
15: iastore
16: aload_1
17: iconst_3
18: iconst_0
19: iastore
20: aload_1
21: areturn