以下哪种Java编码片段更好?
这并不意味着主观,我在寻找基于资源利用率、编译器性能、GC性能等的原因,而不是优雅。哦,括号的位置不算数,所以请不要发表文体评论 采取以下循环以下哪种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) {
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);
}
}