成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

【Java】變量聲明在循環體內還是循環體外你用哪一個?

開發 后端
最近刷知乎的時候看到一個比較有意思的問題,變量聲明在循環體內還是循環體外?這個問題有人認為應該定義循環體外,不應該定義在循環體內。

[[349120]]

 引言

最近刷知乎的時候看到一個比較有意思的問題,變量聲明在循環體內還是循環體外?這個問題有人認為應該定義循環體外,不應該定義在循環體內。很多java代碼優化建議都有這么一條建議:循環內不要不斷創建對象引用 例如:

  1. for (int i = 1; i <= count; i++){ 
  2.     Object obj = new Object(); 

這種做法會導致內存中有count份Object對象引用存在,count很大的話,就耗費內存了,建議為改為:

  1. Object obj = null
  2. for (int i = 0; i <= count; i++) { 
  3.     obj = new Object(); 

這樣的話,內存中只有一份Object對象引用,每次new Object()的時候,Object對象引用指向不同的Object罷了,但是內存中只有一份,這樣就大大節省了內存空間了。這條建議應該也出現過在很多公司的代碼規范上了吧。下面我們就來分析下變量聲明在循環體內和變量聲明循環體外的情況。

效率對比

首先我們先來看看寫在循環體內和詢環體外的效率比對,測試代碼如下:

  1. /** 
  2.  * @author: 公眾號【java金融】 
  3.  * @Date:  
  4.  * @Description: 
  5.  */ 
  6.  
  7. @BenchmarkMode(Mode.AverageTime) // 測試完成時間 
  8. @OutputTimeUnit(TimeUnit.NANOSECONDS) 
  9. @Warmup(iterations = 2) // 預熱 2 輪,每次 1s 
  10. @Measurement(iterations = 5) // 測試 5 輪,每次 1s 
  11. @Fork(1) // fork 1 個線程 
  12. @State(Scope.Thread) 
  13. public class ForEachBenchMark { 
  14.  
  15.  
  16.     public static void main(String[] args) throws RunnerException { 
  17.         Options opt = new OptionsBuilder() 
  18.                 .include(ForEachBenchMark.class.getSimpleName()) 
  19.                 .result("result.json"
  20.                 .resultFormat(ResultFormatType.JSON).build(); 
  21.         new Runner(opt).run(); 
  22.     } 
  23.  
  24.     @Param(value = {"10""50""100"}) 
  25.     private int length; 
  26.  
  27.  
  28.     /** 
  29.      * 循環體外創建對象 
  30.      * @param blackhole 
  31.      */ 
  32.     @Benchmark 
  33.     public void outsideLoop(Blackhole blackhole) { 
  34.         Object object = null
  35.         for (int i = 0; i < length; i++) { 
  36.             object = new Object(); 
  37.             blackhole.consume(object); 
  38.         } 
  39.  
  40.  
  41.     } 
  42.  
  43.     /** 
  44.      * 循環體內創建對象 
  45.      * @param blackhole 
  46.      */ 
  47.     @Benchmark 
  48.     public void insideLoop(Blackhole blackhole) { 
  49.         for (int i = 0; i < length; i++) { 
  50.             Object object = new Object(); 
  51.             blackhole.consume(object); 
  52.  
  53.         } 
  54.  
  55.     } 

測試結果如下:

  1. Benchmark                     (length)  Mode  Cnt    Score    Error  Units 
  2. ForEachBenchMark.insideLoop         10  avgt    5   58.629 ±  8.857  ns/op 
  3. ForEachBenchMark.insideLoop         50  avgt    5  293.726 ±  1.856  ns/op 
  4. ForEachBenchMark.insideLoop        100  avgt    5  587.185 ± 40.424  ns/op 
  5. ForEachBenchMark.outsideLoop        10  avgt    5   59.563 ±  5.057  ns/op 
  6. ForEachBenchMark.outsideLoop        50  avgt    5  305.829 ± 27.476  ns/op 
  7. ForEachBenchMark.outsideLoop       100  avgt    5  584.853 ± 20.289  ns/op 

我們可以發現不管在循環外創建對象和循環內創建對象時間幾乎都是一樣的。

字節碼對比

下面我們準備兩個測試類

  1. public class InsideTest { 
  2.     public static int count = 100; 
  3.     public List<Object> insideLoop() { 
  4.         List<Object> list = new ArrayList<>(); 
  5.         int n = 0; 
  6.         for (; ; ) { 
  7.             if (n > count) { 
  8.               break; 
  9.             } 
  10.             Object o = new Object(); 
  11.             list.add(o); 
  12.         } 
  13.         Object b = 2; 
  14.         return list; 
  15.     } 
  16. public class OutsideTest { 
  17.     public static int count = 100; 
  18. public List<Object> outsideLoop() { 
  19.         List<Object> list = new ArrayList<>(); 
  20.        Object o = null
  21.        int n = 0; 
  22.        for (; ; ) { 
  23.            if (n > count) { 
  24.                break; 
  25.            } 
  26.             o = new Object(); 
  27.             list.add(o); 
  28.         } 
  29.         Object b = 2; 
  30.         return list; 
  31.     } 

這兩個編譯后字節碼幾乎一模一樣,除了循環體外(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。

  1. javac -g  OutsideTest.java 
  2. javap -v  OutsideTest.class 
  1. LocalVariableTable: 
  2.       Start  Length  Slot  Name   Signature 
  3.          28       8     3     o   Ljava/lang/Object; 
  4.           0      46     0  this   Lcom/workit/autoconfigure/autoconfigure/controller/InsideTest; 
  5.           8      38     1  list   Ljava/util/List; 
  6.          10      36     2     n   I 
  7.          44       2     3     b   Ljava/lang/Object; 
  1. LocalVariableTable: 
  2.        Start  Length  Slot  Name   Signature 
  3.            0      49     0  this   Lcom/workit/autoconfigure/autoconfigure/controller/OutsideTest; 
  4.            8      41     1  list   Ljava/util/List; 
  5.           10      39     2     o   Ljava/lang/Object; 
  6.           12      37     3     n   I 
  7.           47       2     4     b   Ljava/lang/Object; 

這是比較極端的情況下有1個solt的差距,如果把上述的代碼 Object b = 2;就不會存在solt復用了。

總結

整體看下來貌似內存和效率都差不多。從“「局部變量作用域最小化」”原則上來說,變量聲明在循環體內更合適一點,這樣代碼的閱讀性更好。

本文轉載自微信公眾號「java金融」,可以通過以下二維碼關注。轉載本文請聯系java金融公眾號。

 

責任編輯:武曉燕 來源: java金融
相關推薦

2020-10-14 12:10:22

Javatry-catch代碼

2021-11-19 14:44:17

樹莓派Linux

2021-11-15 09:53:16

STM32PSPMSP

2010-07-16 11:40:45

KVMXen

2019-04-29 15:27:57

網絡故障工具

2018-02-10 17:59:10

LinuxcURLwget

2023-10-08 11:53:29

2020-06-17 15:00:27

FedoraUbuntuLinux

2021-11-19 09:49:00

CC++語法糖

2022-10-08 09:03:16

JuliaPython機器學習

2011-11-08 08:59:51

云計算IaaSPaaS

2018-06-22 15:52:50

云桌面

2022-04-02 09:05:47

AlmaLinuxRocky LinuCentOS

2018-10-18 14:26:45

云計算架構師管理

2018-11-29 09:45:03

Windows 10Windows版本

2018-07-18 13:29:38

云計算云平臺企業

2017-10-24 15:46:03

VMwareOpenStackvSphere

2018-08-12 23:15:04

iOS Android 操作系統

2017-07-05 11:38:29

互聯網

2020-10-21 18:20:14

UbuntuPop!_OSLinux
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人性视频免费网站 | 夜夜爽99久久国产综合精品女不卡 | 国产精品成人一区二区三区 | 亚洲一二视频 | 91国产精品 | 一二三四在线视频观看社区 | 日韩一区二区黄色片 | 狠狠爱免费视频 | 日本久久久影视 | 中文字幕亚洲欧美 | 亚洲乱码国产乱码精品精98午夜 | 中文字幕第十五页 | 在线视频亚洲 | 91视频国产精品 | 日韩欧美亚洲 | 欧美一区二区三区在线播放 | 欧美在线综合 | 黄色在线免费网站 | 日韩中文字幕在线播放 | 成人精品 | 国产成人免费视频网站视频社区 | 中文字幕在线一区二区三区 | 91网视频 | 日韩欧美成人一区二区三区 | 国产精品毛片无码 | 在线亚洲免费 | 久久一区二区三区免费 | 欧美一区二区在线看 | 这里只有精品99re | 午夜精品久久久久久不卡欧美一级 | 黄色免费在线观看网站 | 欧美精品区 | 日操操夜操操 | 免费黄色在线 | 国产激情精品 | 99亚洲精品| 精品视频一区二区三区在线观看 | 亚洲欧美精品在线 | 97久久精品午夜一区二区 | www.887色视频免费 | 日本免费在线观看视频 |