[ Java ] 变量声明在循环体内还是循环体外? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhaoritian19
V2EX    Java

[ Java ] 变量声明在循环体内还是循环体外?

  •  
  •   zhaoritian19 2019-12-30 15:17:34 +08:00 5207 次点击
    这是一个创建于 2183 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这是一个已经被讨论了很久的问题了,能查到的答案各种都有,请问各位大佬们有什么高见?

    小白我现在项目中遇到了类似的问题,循环遍历一个对象集合,然后取其中的某些属性放入另一个对象集合中,目前是在循环的过程中 new 了新的对象,然后放入新的 list 中。在联调的时还在循环的时候日志打印了新的实体对象,但是却内存溢出项目挂掉了。 很费解,lst 的大小也就 2000 多个对象,有那么费内存吗?为什么会内存溢出?是不是将变量的声明放在循环外会好一些?希望大佬们能帮忙答疑,谢谢 
    15 条回复    2020-01-06 11:55:22 +08:00
    Esioner
        1
    Esioner  
       2019-12-30 15:35:51 +08:00
    list 存的是对象的引用把,如果你把变量声明放到外面会导致数据异常的问题把
    Arsenal16
        2
    Arsenal16  
       2019-12-30 15:39:58 +08:00 via Android
    list.stream().filter(你的过滤条件).map(你要映射的属性).collect(Collectors.toList());
    Java8 的话直接用这个吧。
    你那个又没代码,菜鸡如我,没法排查。
    Arsenal16
        3
    Arsenal16  
       2019-12-30 15:47:03 +08:00 via Android
    你这个应该放在循环体内创建对象,然后添加到 list
    cruii
        4
    cruii  
       2019-12-30 17:24:46 +08:00
    这样问问题就跟不贴图说自己电脑蓝屏了怎么解决一样
    matepi
        5
    matepi  
       2019-12-30 17:36:32 +08:00
    不会,循环体内变量实际会被优化提前到循环起始前
    和内存占用真正有关的是 new 动作
    要看你其他代码,包括 new 动作里面进一步的 new
    zhaoritian19
        6
    zhaoritian19  
    OP
       2019-12-30 17:59:53 +08:00
    @matepi 没有在 new 的实体对象里面进一步 new 别的对象,我也感觉单单是循环里面 new 实体对象不会导致内存溢出,而且才 1000 多个,GC 应该能处理的了。
    zhaoritian19
        7
    zhaoritian19  
    OP
       2019-12-30 18:01:14 +08:00
    @Arsenal16 老项目了用的 java7,没有升级到 java8。 如果是 8 就不会用循环来做了
    chendy
        8
    chendy  
       2019-12-30 18:14:17 +08:00
    内存溢出的话,用 -XX:+HeapDumpOnOutOfMemoryError 导出 dump,然后 mat 分析 dump 看是什么东西占用了太多内存
    2000 不多,但是也不知道每个对象多大,所以不好说…
    passerbytiny
        9
    passerbytiny  
       2019-12-30 18:16:27 +08:00
    变量声明应该放到循环体外(然并卵,减少的内存占用相对来说可以忽略),但给 list 的对象一定是在循环体内 new 出来的。

    list 上万都没问题,你这个能溢出应该是其他原因,需要根据 JVM 异常日志去定位。
    palmers
        10
    palmers  
       2019-12-30 19:39:03 +08:00
    得看看是堆内存还是栈内存 还有 同意 8#的同学把对应日志 dump 出来看看占用在哪里 问题原因应该就出来了
    JohnZorn
        11
    JohnZorn  
       2019-12-31 01:04:00 +08:00 via Android
    2000 个就溢出,,java 再费内存也没这么个费法啊
    nnnToTnnn
        12
    nnnToTnnn  
       2019-12-31 08:47:40 +08:00
    Java 无论是在循环体内还是循环体外,由于 java 特定的 gc 机制,就算你在循环体内声明了变量,也不可能内存溢出!!!

    除非有些引用没有被 gc,例如很简单的 ThreadLocal 中使用了 map,这种内存溢出的操作。
    LaughingCat
        13
    LaughingCat  
       2019-12-31 09:46:47 +08:00
    我以前也遇到过这种循环 new 溢出的问题,当在循环次数达到一定数量时,new 操作会在占用大量的内存空间,解决方式是在外面 new 一个对象,这个对象有处理数据的构造函数,然后在循环里面对该对象进行构造函数赋值就能达到你要的循环 new 的效果。
    rizon
        14
    rizon  
       2019-12-31 15:05:36 +08:00
    这事我也很纠结,正常来说,从代码的可读性来说,放到循环体内生命更合适,但是很多人又说处于性能考虑应该放到循环体外。
    我一般考虑可读性。 但是也是希望能得到一个更明确点的答案。
    至于内存泄漏问题,在 java 里是不存在的,搞 C 的才有这个问题。
    mightofcode
        15
    mightofcode  
       2020-01-06 11:55:22 +08:00
    贴代码比较好,看描述看不明白
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1056 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 17:37 PVG 01:37 LAX 09:37 JFK 12:37
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86