自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

【Java】變量聲明在循環(huán)體內(nèi)還是循環(huán)體外你用哪一個?

開發(fā) 后端
最近刷知乎的時候看到一個比較有意思的問題,變量聲明在循環(huán)體內(nèi)還是循環(huán)體外?這個問題有人認(rèn)為應(yīng)該定義循環(huán)體外,不應(yīng)該定義在循環(huán)體內(nèi)。

[[349120]]

 引言

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

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

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

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

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

效率對比

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

  1. /** 
  2.  * @author: 公眾號【java金融】 
  3.  * @Date:  
  4.  * @Description: 
  5.  */ 
  6.  
  7. @BenchmarkMode(Mode.AverageTime) // 測試完成時間 
  8. @OutputTimeUnit(TimeUnit.NANOSECONDS) 
  9. @Warmup(iterations = 2) // 預(yù)熱 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.      * 循環(huán)體外創(chuàng)建對象 
  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.      * 循環(huán)體內(nèi)創(chuàng)建對象 
  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.     } 

測試結(jié)果如下:

  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 

我們可以發(fā)現(xiàn)不管在循環(huán)外創(chuàng)建對象和循環(huán)內(nèi)創(chuàng)建對象時間幾乎都是一樣的。

字節(jié)碼對比

下面我們準(zhǔn)備兩個測試類

  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.     } 

這兩個編譯后字節(jié)碼幾乎一模一樣,除了循環(huán)體外(OutsideTest )常量池多了一個Object o = null變量還有的話就是LocalVariableTable有點區(qū)別,變量在循環(huán)體內(nèi)的話公用了一個變量槽(o和b變量) outsideLoop在stack frame中定義了4個slot, 而intsideLoop只定義了3個slot 在outsideLoop中,變量o和b分別占用了不同的slot,在intsideloop中,變量o和b復(fù)用一個slot。所以outsideLoop的stack frame比intsideLoop多占用1個solt內(nèi)存。執(zhí)行以下命令就可以找到字節(jié)碼中的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復(fù)用了。

總結(jié)

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

本文轉(zhuǎn)載自微信公眾號「java金融」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系java金融公眾號。

 

責(zé)任編輯:武曉燕 來源: java金融
相關(guān)推薦

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

網(wǎng)絡(luò)故障工具

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機器學(xué)習(xí)

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

云計算架構(gòu)師管理

2018-11-29 09:45:03

Windows 10Windows版本

2018-07-18 13:29:38

云計算云平臺企業(yè)

2017-10-24 15:46:03

VMwareOpenStackvSphere

2018-08-12 23:15:04

iOS Android 操作系統(tǒng)

2017-07-05 11:38:29

互聯(lián)網(wǎng)

2020-10-21 18:20:14

UbuntuPop!_OSLinux
點贊
收藏

51CTO技術(shù)棧公眾號