以下哪种Java编码片段更好?

以下哪种Java编码片段更好?,java,scope,Java,Scope,这并不意味着主观,我在寻找基于资源利用率、编译器性能、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) {

这并不意味着主观,我在寻找基于资源利用率、编译器性能、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


还有很多其他情况下,我倾向于将变量的范围扩大到可能不必要的范围,所以我想我会在这里要求澄清我的知识差距。还要注意初始化时变量的赋值是否涉及新运算符。这些半风格的半优化有什么不同吗?

第二种是我更喜欢的。除了范围之外,没有其他功能上的区别

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

另外,在这段代码中,您应该使用
int
Integer.parseInt()
而不是
Integer
Integer.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
检索):

从“ScopeTest.java”编译而来
类ScopeTest扩展了java.lang.Object{
ScopeTest();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
外部公共void(java.lang.String[]);
代码:
0:iconst_0
1:invokestatic#2;//方法java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4:astore_2
5:aload_1
6:astore 4
8:aload 4
10:排列长度
11:istore 5
13:iconst_0
14:历史记录6
16:iload 6
18:iload 5
20:if_icmpge 55
23:aload 4
25:iload 6
27:aaload
28:astore 7
30:7分
32:invokestatic#3;//方法java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
35:astore_3
36:aload_2
37:invokevirtual#4;//方法java/lang/Integer.intValue:()I
40:aload_3
41:invokevirtual#4;//方法java/lang/Integer.intValue:()I
44:iadd
45:invokestatic#2;//方法java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
48:astore_2
49:iinc 6,1
52:转到16
55:返回
内部为public void(java.lang.String[]);
代码:
0:iconst_0
1:invokestatic#2;//方法java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4:astore_2
5:aload_1
6:astore_3
7:aload_3
8:排列长度
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;//方法java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
32:astore 7
34:aload_2
35:invokevirtual#4;//方法java/lang/Integer.intValue:()I
38:aload 7
40:invokevirtual#4;//方法java/lang/Integer.intValue:()I
43:iadd
44:invokestatic#2;//方法java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
47:astore_2
48:iinc 5,1
51:goto 14
54:返回
}
与我的预期相反,两者之间有一个区别:在
outside()
中,变量
i
仍然占用一个寄存器,即使它从实际代码中被省略(请注意,所有
iload
istore
指令都指向一个更高的寄存器)

JIT编译器应该能够很快地解决这一差异,但您仍然可以看到,限制作用域是一种很好的做法


(关于我前面的补充说明,您可以看到,要添加两个整数对象,Java必须使用
intValue
将这两个对象取消装箱,添加它们,然后使用
valueOf
创建一个新的整数。除非绝对必要,否则不要这样做,因为这样做毫无意义且速度较慢。)

除了在上一次迭代中,在第二个示例中,当引用被更快地清除时,它没有显著的区别(这是我的偏好-不是因为这个原因,而是因为清晰。)

将范围保持在尽可能小的范围内。hotspot VM不进行分析以确定何时不再可以访问引用,并在此基础上在堆栈上而不是堆上分配一些对象。保持范围尽可能小有助于这一过程


我想问你为什么用整数而不是简单的
int
…或者这只是一个例子?

第二个更好。尽可能缩小变量的范围使代码更易于阅读和维护,这比这些示例之间的性能差异更为重要,因为这些差异很小,很容易优化。

两者都不是<代码>整数。值为(0)将使用对缓存的0的引用。:)

第二种要好得多,因为第一种样式应该只在C代码中作为强制样式使用。Java允许内联声明来最小化变量的范围,您应该利用这一点。但您的代码可以进一步改进:

int total = 0;
for (String str: stringList) {
    try {
        total += Integer.valueOf(str);
    } catch(NumberFormationException nfe) {
        // more code to deal with the error
    }
}
这遵循Java代码样式约定。请在此处阅读完整的指南:
在本例中,您正在实例化一个
整数
int total = 0;
for (String str: stringList) {
    try {
        total += Integer.valueOf(str);
    } catch(NumberFormationException nfe) {
        // more code to deal with the error
    }
}
int total = 0;
for (String str : string_list)
{
    int i = Integer.parseInt(str);
    total += i;
}
import java.util.ArrayList;
import java.util.List;

public class Int {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("10");
        list.add("20");
        int total = 0;
        for (String str : list) {
            int val = 0;
            for (char c : str.toCharArray()) {
                val = val * 10 + (int) c - 48;
            }
            total += val;
        }
        System.out.print(total);
    }
}
private static Random rnd = new Random();

public static void test() {
    int x = rnd.nextInt();
    System.out.println(x);

    int y = rnd.nextInt();
    System.out.println(y);

    int z = rnd.nextInt();
    System.out.println(z);      
}
public static void test() {
    {
        int x = rnd.nextInt();
        System.out.println(x);
    }

    {
        int y = rnd.nextInt();
        System.out.println(y);
    }

    {
        int z = rnd.nextInt();
        System.out.println(z);
    }
}