java循环体内声明变量_Java变量声明在循环体内还是循环体外,你用哪一个?

@BenchmarkMode(Mode.AverageTime) // 测试完成时间@OutputTimeUnit(TimeUnit.NANOSECONDS)@Warmup(iterations = 2) // 预热 2 轮,每次 1s@Measurement(iterations = 5) // 测试 5 轮,每次 1s@Fork( 1) // fork 1 个线程@State(Scope.Thread)publicclassForEachBenchMark{

publicstaticvoidmain(String[] args)throwsRunnerException{Options opt = newOptionsBuilder.include(ForEachBenchMark.class.getSimpleName).result( "result.json").resultFormat(ResultFormatType.JSON).build;newRunner(opt).run;}

@Param(value = { "10", "50", "100"})privateintlength;

/*** 循环体外创建对象* @paramblackhole*/@BenchmarkpublicvoidoutsideLoop(Blackhole blackhole){Object object = null;for( inti = 0; i < length; i++) {object = newObject;blackhole.consume(object);}

}

/*** 循环体内创建对象* @paramblackhole*/@BenchmarkpublicvoidinsideLoop(Blackhole blackhole){for( inti = 0; i < length; i++) {Object object = newObject;blackhole.consume(object);

}

}}

测试结果如下:

Benchmark (length) Mode Cnt Score Error Units

ForEachBenchMark.insideLoop 10avgt 558.629± 8.857ns/op

ForEachBenchMark.insideLoop 50avgt 5293.726± 1.856ns/op

ForEachBenchMark.insideLoop 100avgt 5587.185± 40.424ns/op

ForEachBenchMark.outsideLoop 10avgt 559.563± 5.057ns/op

ForEachBenchMark.outsideLoop 50avgt 5305.829± 27.476ns/op

ForEachBenchMark.outsideLoop 100avgt 5584.853± 20.289ns/op

d811d96858c485181c4c990db875c22c.png

我们可以发现不管在循环外创建对象和循环内创建对象时间几乎都是一样的。

字节码对比

下面我们准备两个测试类

publicclassInsideTest{publicstaticint count = 100;publicList insideLoop {List list= newArrayList<>;int n = 0;for(; ; ) {if(n > count) {break;}Object o = newObject;list.add(o);}Object b = 2;returnlist;}}publicclassOutsideTest{publicstaticint count = 100;publicList outsideLoop {List list= newArrayList<>;Object o = null;int n = 0;for(; ; ) {if(n > count) {break;}o = newObject;list.add(o);}Object b = 2;returnlist;}

这两个编译后字节码几乎一模一样,除了循环体外(OutsideTest )常量池多了一个Object o = null变量还有的话就是LocalVariableTable有点区别,变量在循环体内的话公用了一个变量槽(o和b变量)outsideLoop在stack frame中定义了4个slot, 而intsideLoop只定义了3个slot 在outsideLoop中,变量o和b分别占用了不同的slot,在intsideLoop中,变量o和b复用一个slot。所以outsideLoop的stack frame比intsideLoop多占用1个solt内存。执行以下命令就可以找到字节码中的LocalVariableTable。

javac-gOutsideTest.javajavap-vOutsideTest.class

LocalVariableTable:StartLength Slot Name Signature288 3 o Ljava/lang/Object;046 0 this Lcom/workit/autoconfigure/autoconfigure/controller/InsideTest;838 1 list Ljava/util/List;1036 2 n I442 3 b Ljava/lang/Object;

LocalVariableTable:StartLength Slot Name Signature049 0 this Lcom/workit/autoconfigure/autoconfigure/controller/OutsideTest;841 1 list Ljava/util/List;1039 2 o Ljava/lang/Object;1237 3 n I472 4 b Ljava/lang/Object;

这是比较极端的情况下有1个solt的差距,如果把上述的代码 Object b = 2;就不会存在 solt复用了。

总结

整体看下来貌似内存和效率都差不多。从“ 「局部变量作用域最小化」”原则上来说,变量声明在循环体内更合适一点,这样代码的阅读性更好。

参考:https://www.zhihu.com/question/31751468返回搜狐,查看更多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值