zwbgx04 2011-10-28 17:22
浏览 955
已采纳

关于Java语言for循环内外变量定义的问题

今天被TeamLeader批了一顿,本来想和他争论争论的,后来感觉自己也不清楚,遂只有来Iteye讨教讨教了。
这是个关于在for循环内外变量定义的问题,先看代码:
[code="java"]
public class Test2 {

public static void main(String[] args) {

    // 放入10000000的元素
    List<Object> list = new ArrayList<Object>(10000000);
    for(int i = 0; i < 10000000; i++) {
        list.add(i, new Object());
    }

    // 做10次循环,求均值
    for(int j = 0; j < 10; j++) {

        // 变量在循环内定义
        long t1 = System.currentTimeMillis();
        for(Iterator<Object> iterator = list.iterator(); iterator.hasNext();) {
            Object object = iterator.next();
        }
        long t2 = System.currentTimeMillis();
        System.out.println("循环内" + (j + 1) + "次, 时间:" + (t2 - t1) + ";");

        // 变量在循环外定义
        t1 = System.currentTimeMillis();
        Object object = null;
        for(Iterator<Object> iterator = list.iterator(); iterator.hasNext();) {
            object = iterator.next();
        }
        t2 = System.currentTimeMillis();
        System.out.println("循环外" + (j + 1) + "次, 时间:" + (t2 - t1) + ";");
    }
}

}

/*其中一次的运行结果

  • 变量在循环内定义 变量在循环外定义 *1次循环 359 359 *2次循环 360 343 *3次循环 344 360 *4次循环 359 359 *5次循环 344 359 *6次循环 360 359 *7次循环 360 359 *8次循环 344 359 *9次循环 344 359 *10次循环 344 359 */ [/code]

我在工作中有一段代码是放到循环内定义的,主要是习惯,以及变量最小作用域的理念。但teamleader告诉我要放到循环外面,放在里面性能不好,不太理解。这个问题发生后,我也在网络寻找答案,但结果差不多一半一半,有建议在内部定义,也有建议在外部定义,所以就更糊涂了...我现在所知道的有:在内部定义,满足变量最小作用域的理念,循环外没有使用这个变量,该变量就不会在循环外定义;但teamleader说在内部定义会多次申请栈内存,影响性能,但我写了上面的例子和查了下资料,也没有弄太清这里面是如何影响性能的,请帮助详细讲解下两种定义方式的好坏,及其原因,和jdk版本是否有关系。

  • 写回答

6条回答 默认 最新

  • iteye_6273 2011-11-01 09:49
    关注

    从性能角度而言
    [quote]teamleader说在内部定义会多次申请栈内存,影响性能[/quote],放在循环内部定义,确实会多次申请栈帧的内存空间(java中一个线程对应一个Java栈,每次方法调用会向栈中压入一个新帧,帧中存储着参数、局部变量、中间运算结果等等数据,方法调用结束后当前的帧就被弹出了,可参考我的一篇文章[url]http://boy00fly.iteye.com/blog/1096637[/url]),为什么会多占用栈空间内,原因很简单,每次循环都要重复定义局部变量,而如果放在循环体外,每次只要移动引用指向的堆内存地址即可,不必重新申请内存空间了。
    其实话说回来,这样对性能的影响其实可以忽略不计,没什么大的问题,非要纠结这个性能问题的话,就如我上面说的那样。
    [code="java"]
    public V get(Object key)

    {

    if (key == null)

    return getForNullKey();

    int hash = hash(key.hashCode());

    for (Entry e = table[indexFor(hash, table.length)]; e != null; e = e.next)
    {

    Object k;

    if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

    return e.value;

    }

    return null;

    }

    [/code]
    上面这段代码是jdk中HashMap的源码,你看源码的Object k定义就在循环体内部的! :wink:

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?