请教一个java编码规范的问题?
悬赏:5 发布时间:2008-07-23 提问人:bigbird (初级程序员)
公司的java编码规范对于如下写法:
for(int i=0;i<personId.length;i++){
SignUpByCourseVO vo = new SignUpByCourseVO();
......
}
要求这么写:
SignUpByCourseVO vo=null;
for(int i=0;i<personId.length;i++){
vo = new SignUpByCourseVO();
......
}
我不是很理解具体有什么不同,因为无论vo在循环外,还是循环内定义,都是要在循环内初始化的,第一种写法会有性能问题吗?
请哪位帮解答一下?多谢!
问题补充:
多谢你的解答。还是有个疑问,两种实现效率上没什么差别,那在内存的使用上有没有差别呢,第一种写法每次循环时都会创建一个vo引用吧?这样如果数据量大时,是不是就有内存上的差异了,也就是说第一种比第二种更耗内存?
该问题已经关闭: 感谢各位解答,本人不是想深究什么技术东西,只是有些疑惑,想知道个为什么。毕竟网络上藏龙卧虎。
for(int i=0;i<personId.length;i++){
SignUpByCourseVO vo = new SignUpByCourseVO();
......
}
要求这么写:
SignUpByCourseVO vo=null;
for(int i=0;i<personId.length;i++){
vo = new SignUpByCourseVO();
......
}
我不是很理解具体有什么不同,因为无论vo在循环外,还是循环内定义,都是要在循环内初始化的,第一种写法会有性能问题吗?
请哪位帮解答一下?多谢!
问题补充:
多谢你的解答。还是有个疑问,两种实现效率上没什么差别,那在内存的使用上有没有差别呢,第一种写法每次循环时都会创建一个vo引用吧?这样如果数据量大时,是不是就有内存上的差异了,也就是说第一种比第二种更耗内存?
该问题已经关闭: 感谢各位解答,本人不是想深究什么技术东西,只是有些疑惑,想知道个为什么。毕竟网络上藏龙卧虎。
回答
从语句上分析,循环外创建效率会比循环内创建效率高,但是现在编译器有优化功能,这种情况,两种写法经过优化后字节码应该是一样的,也就是说,优化编译后,执行效率一样。
从作用域来讲,后一种往往比较好,把对象作用于限制在循环体内,避免其污染循环体外。
从作用域来讲,后一种往往比较好,把对象作用于限制在循环体内,避免其污染循环体外。
sunsong (初级程序员) 2008-07-23
package com.sss.test.String;
public class TestLoop {
public void test1(){
String str;
for(int i=0;i<100;i++){
str= new String("hello");
System.out.println(str);
}
}
public void test2(){
for(int i=0;i<100;i++){
String str=new String("hello");
System.out.println(str);
}
}
}编译该类,然后在命令行中位于相应目录使用javap -verbose TestLoop得到字节码,对比一下:
public void test1();
Code:
Stack=3, Locals=3, Args_size=1
0: iconst_0
1: istore_2
2: goto 25
5: new #15; //class java/lang/String
8: dup
9: ldc #17; //String hello
11: invokespecial #19; //Method java/lang/String."<init>":(Ljava/lang/String;)V
14: astore_1
15: getstatic #22; //Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_1
19: invokevirtual #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: iinc 2, 1
25: iload_2
26: bipush 100
28: if_icmplt 5
31: return
LineNumberTable:
line 6: 0
line 7: 5
line 8: 15
line 6: 22
line 11: 31
LocalVariableTable:
Start Length Slot Name Signature
0 32 0 this Lcom/sss/test/String/TestLoop;
15 10 1 str Ljava/lang/String;
2 29 2 i I
===============================================================
public void test2();
Code:
Stack=3, Locals=3, Args_size=1
0: iconst_0
1: istore_1
2: goto 25
5: new #15; //class java/lang/String
8: dup
9: ldc #17; //String hello
11: invokespecial #19; //Method java/lang/String."<init>":(Ljava/lang/String;)V
14: astore_2
15: getstatic #22; //Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_2
19: invokevirtual #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: iinc 1, 1
25: iload_1
26: bipush 100
28: if_icmplt 5
31: return
LineNumberTable:
line 15: 0
line 16: 5
line 17: 15
line 15: 22
line 20: 31
LocalVariableTable:
Start Length Slot Name Signature
0 32 0 this Lcom/sss/test/String/TestLoop;
2 29 1 i I
15 7 2 str Ljava/lang/String;
除了LocalVariableTable中变量顺序不一样,执行逻辑上没有区别。
说明编译器已经进行了优化(我的环境是jdk1.5)
基于上述实验,我认为采用第二种写法更好。
public class TestLoop {
public void test1(){
String str;
for(int i=0;i<100;i++){
str= new String("hello");
System.out.println(str);
}
}
public void test2(){
for(int i=0;i<100;i++){
String str=new String("hello");
System.out.println(str);
}
}
}编译该类,然后在命令行中位于相应目录使用javap -verbose TestLoop得到字节码,对比一下:
public void test1();
Code:
Stack=3, Locals=3, Args_size=1
0: iconst_0
1: istore_2
2: goto 25
5: new #15; //class java/lang/String
8: dup
9: ldc #17; //String hello
11: invokespecial #19; //Method java/lang/String."<init>":(Ljava/lang/String;)V
14: astore_1
15: getstatic #22; //Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_1
19: invokevirtual #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: iinc 2, 1
25: iload_2
26: bipush 100
28: if_icmplt 5
31: return
LineNumberTable:
line 6: 0
line 7: 5
line 8: 15
line 6: 22
line 11: 31
LocalVariableTable:
Start Length Slot Name Signature
0 32 0 this Lcom/sss/test/String/TestLoop;
15 10 1 str Ljava/lang/String;
2 29 2 i I
===============================================================
public void test2();
Code:
Stack=3, Locals=3, Args_size=1
0: iconst_0
1: istore_1
2: goto 25
5: new #15; //class java/lang/String
8: dup
9: ldc #17; //String hello
11: invokespecial #19; //Method java/lang/String."<init>":(Ljava/lang/String;)V
14: astore_2
15: getstatic #22; //Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_2
19: invokevirtual #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: iinc 1, 1
25: iload_1
26: bipush 100
28: if_icmplt 5
31: return
LineNumberTable:
line 15: 0
line 16: 5
line 17: 15
line 15: 22
line 20: 31
LocalVariableTable:
Start Length Slot Name Signature
0 32 0 this Lcom/sss/test/String/TestLoop;
2 29 1 i I
15 7 2 str Ljava/lang/String;
除了LocalVariableTable中变量顺序不一样,执行逻辑上没有区别。
说明编译器已经进行了优化(我的环境是jdk1.5)
基于上述实验,我认为采用第二种写法更好。
sunsong (初级程序员) 2008-07-23
public class Test {
static String s = "sssssssssssssssssssssssssssssss";
static {
System.out.println(s);
}
public static void main(String[] args) {
Long startTime = System.currentTimeMillis();
Test test = null;
for (int i = 0; i < 1000000; i++) {
test = new Test();
}
Long endTime = System.currentTimeMillis() - startTime;
System.gc();
Long startTime2 = System.currentTimeMillis();
for (int j = 0; j < 1000000; j++) {
Test test2 = new Test();
}
Long endTime2 = System.currentTimeMillis() - startTime2;
System.out.println(endTime2);
System.out.println(endTime);
}
}
前面的效率比后面的高 test下
visoin (中级程序员) 2008-07-23
做了个试验,两种不同的写法,产生的class目标文件是不同的,第一种方法产生的class文件体积稍大。分别对两个class文件进行反编译,获得的源文件与最初的源文件完全一样。由此,我怀疑编译器没有对这种情况进行优化,但这只是猜测。
将符号声明写在循环内,与写在循环外面相比,会有部分额外的开销,在循环次数不是巨大的情况下,我认为对性能的影响可以忽略不计的。
所以,要求写在循环外声明类变量符号,主要还是出于性能的考虑。
将符号声明写在循环内,与写在循环外面相比,会有部分额外的开销,在循环次数不是巨大的情况下,我认为对性能的影响可以忽略不计的。
所以,要求写在循环外声明类变量符号,主要还是出于性能的考虑。
qdzheng (中级程序员) 2008-07-23
to visoin :
你把1000000修改一下看看,在不同数量级效果不一样。具体原因尚未得知
可参看csdn相关讨论
http://topic.csdn.net/t/20060627/15/4846244.html
你把1000000修改一下看看,在不同数量级效果不一样。具体原因尚未得知
可参看csdn相关讨论
http://topic.csdn.net/t/20060627/15/4846244.html
sunsong (初级程序员) 2008-07-23
我认为第一种好,容易懂。
如果没有足够的理由,没必要用第二种。
新手不需要考虑这样的问题,公司让怎么写就怎么写,很多时候就是某个老大的习惯而已,这种问题没什么意义。
像String和StringBuffer哪个更好,这样的问题也不要去想,爱用哪个用拿个。
性能,不是由这些东西影响的。
如果没有足够的理由,没必要用第二种。
新手不需要考虑这样的问题,公司让怎么写就怎么写,很多时候就是某个老大的习惯而已,这种问题没什么意义。
像String和StringBuffer哪个更好,这样的问题也不要去想,爱用哪个用拿个。
性能,不是由这些东西影响的。
王者之剑 (初级程序员) 2008-07-24




