sel*_*bie 10 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 */
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,假设当Method1和Method2返回时,"bytearray"是垃圾收集的候选者,因为操作bytearray变量的代码都不会持有超出方法本身末尾的引用.
Method2是否通过避免调用"new"来更快地(或不同地)运行?或者上述两种实现是否相同?在任何一种情况下,Java编译器或运行时都可以进行优化以避免为这个短暂的临时缓冲区命中内存分配器的开销吗?
gus*_*afc 12
哪种形式最快?取决于JIT - 它们可能是等价的.很少(如果有的话)程序会注意到差异,如果有的话.
哪种形式最好?几乎无一例外,让你的程序更具可读性的那个.
但是,无论我们是否会注意到,是否存在任何实际差异?我们来看一下!
class ArrayTest {
public int[] withNew() {
int[] arr = new int[4];
return arr;
}
public int[] withInitializer() {
int[] arr = {0, 0, 0, 0};
return arr;
}
}
Run Code Online (Sandbox Code Playgroud)
我们用以下方法拆卸它javap -c ArrayTest
:
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
}
Run Code Online (Sandbox Code Playgroud)
不,在这种情况下它们不一样 - 使用初始化器形式会使插槽单独设置为0,这有点无意义,因为它们已经被数组分配归零.所以,它基本上等同于:
public int[] withNewAndSettingExplicitly() {
int[] arr = new int[4];
arr[0] = 0;
arr[1] = 0;
arr[2] = 0;
arr[3] = 0;
return arr;
}
Run Code Online (Sandbox Code Playgroud)
虽然这可以编译成另一组字节代码,但大致相同但不完全相同:
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
Run Code Online (Sandbox Code Playgroud)
因此,故事的寓意是这样的:如果你想要所有的元素设置0
,你生成的字节码较少new int[size]
(可能更快或更快),但你也必须输入更少(这是一个很大的胜利) .如果要在分配数组时直接设置数组中的值,请使用代码中看起来最好的值,因为生成的代码与您选择的任何形式几乎相同.
现在,回答你的实际问题:
Method2是否通过避免调用"new"来更快地(或不同地)运行?
正如我们所看到的,new
它只是隐藏在初始化语法后面(查找newarray
操作码).顺便说一句,JVM中的分配非常便宜(世代垃圾收集器具有令人愉快的副作用).
或者上述两种实现是否相同?
正如我们所看到的那样 - 并不完全,但不太可能有人会注意到这种差异.
在任何一种情况下,Java编译器或运行时都可以进行优化以避免为这个短暂的临时缓冲区命中内存分配器的开销吗?
再次 - 分配很便宜,所以不要担心.尽管如此,最近的JVM还有一个名为转义分析的小功能,它可能导致数组被分配堆栈而不是堆分配.
归档时间: |
|
查看次数: |
3771 次 |
最近记录: |