gpt4 book ai didi

java - 以下哪个 Java 编码片段比较好?

转载 作者:搜寻专家 更新时间:2023-11-01 01:30:19 26 4
gpt4 key购买 nike

这并不是主观的,我正在寻找基于资源利用、编译器性能、GC 性能等而不是优雅的原因。哦,括号的位置不算在内,所以请不要发表风格评论。

走下面的循环;

Integer total = new Integer(0);
Integer i;
for (String str : string_list)
{
i = Integer.parse(str);
total += i;
}

相对于...

Integer total = 0;
for (String str : string_list)
{
Integer i = Integer.parse(str);
total += i;
}

在第一个中,i 是函数作用域,而在第二个中,它在循环中作用域。我一直认为(相信)第一个会更有效率,因为它只引用一个已经分配在堆栈上的现有变量,而第二个会在循环的每次迭代中插入和弹出 i。

在很多其他情况下,我倾向于将变量的范围设定得比可能需要的范围更广,所以我想我会在这里问一下,以消除我的知识空白。另请注意,初始化时变量的赋值涉及或不涉及 new 运算符。这些半文体半优化中的任何一种都会产生任何影响吗?

最佳答案

第二个是我更喜欢的。除了作用域之外,没有任何功能上的区别。

在每次迭代中设置相同的变量没有区别,因为 Integer 是一个不可变的类。现在,如果您修改一个对象而不是每次都创建一个新对象,那么就会有所不同。

作为旁注,在此代码中,您应该使用 intInteger.parseInt() 而不是 IntegerInteger.parse()。您引入了很多不必要的装箱和拆箱操作。


编辑:我已经有一段时间没有研究字节码了,所以我想我又要动手了。

这是我编译的测试类:

class ScopeTest {
public void outside(String[] args) {
Integer total = 0;
Integer i;
for (String str : args)
{
i = Integer.valueOf(str);
total += i;
}
}
public void inside(String[] args) {
Integer total = 0;
for (String str : args)
{
Integer i = Integer.valueOf(str);
total += i;
}
}
}

字节码输出(编译后使用 javap -c ScopeTest 检索):

Compiled from "ScopeTest.java"
class ScopeTest extends java.lang.Object{
ScopeTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public void outside(java.lang.String[]);
Code:
0: iconst_0
1: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_2
5: aload_1
6: astore 4
8: aload 4
10: arraylength
11: istore 5
13: iconst_0
14: istore 6
16: iload 6
18: iload 5
20: if_icmpge 55
23: aload 4
25: iload 6
27: aaload
28: astore 7
30: aload 7
32: invokestatic #3; //Method java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
35: astore_3
36: aload_2
37: invokevirtual #4; //Method java/lang/Integer.intValue:()I
40: aload_3
41: invokevirtual #4; //Method java/lang/Integer.intValue:()I
44: iadd
45: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
48: astore_2
49: iinc 6, 1
52: goto 16
55: return

public void inside(java.lang.String[]);
Code:
0: iconst_0
1: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_2
5: aload_1
6: astore_3
7: aload_3
8: arraylength
9: istore 4
11: iconst_0
12: istore 5
14: iload 5
16: iload 4
18: if_icmpge 54
21: aload_3
22: iload 5
24: aaload
25: astore 6
27: aload 6
29: invokestatic #3; //Method java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
32: astore 7
34: aload_2
35: invokevirtual #4; //Method java/lang/Integer.intValue:()I
38: aload 7
40: invokevirtual #4; //Method java/lang/Integer.intValue:()I
43: iadd
44: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
47: astore_2
48: iinc 5, 1
51: goto 14
54: return

}

出乎我的意料,两者之间有一个区别:在 outside() 中,变量 i 仍然占用一个寄存器,即使它被省略了实际代码(请注意,所有 iloadistore 指令都指向高一个寄存器)。

JIT 编译器应该很快解决这种差异,但您仍然可以看到限制范围是一种很好的做法。

(关于我之前的旁注,您可以看到要添加两个 Integer 对象,Java 必须使用 intValue 将它们拆箱,添加它们,然后使用 创建一个新的 Integer valueOf。除非绝对必要,否则不要这样做,因为它毫无意义而且速度较慢。)

关于java - 以下哪个 Java 编码片段比较好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2885623/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com