GC并在for循环中分配值

时间:2016-05-26 08:21:22

标签: java variables for-loop garbage-collection variable-assignment

我有一位朋友告诉我以下情况,但我不能说明原因。

import React from 'react';
import ReactDOM from 'react-dom';

export default class DarkLabel extends React.Component {

    componentWillMount() {
        this.setState({
            editing: false,
            content: this.props.content
        })
    }

    handleEditing(e) {
        this.setState({
            content: e.target.value
        });
        console.log(e.target)
        this.props.edit_callback(e.target.value);
    }

    truncate(limit) {
        var content = '';
        if (this.state.content.length > limit) {
            content = <abbr title={this.state.content}>
                {this.props.right_icon 
                     ? this.state.content.substr(0, (limit - 7)) + '...' 
                     : this.state.content.substr(0, (limit - 2)) + '...'}
            </abbr>
        } else {
            content = this.state.content;
        }
        return content;
    }

    onBlur() {
        alert('test')
        }

    render() {
        var icon = '', content = '', contentRaw = this.state.content;
        var rightIcon = '';
        if (this.props.icon && this.props.icon.indexOf('.png') != -1) {
            icon = <div className="icon"><img src={this.props.icon}/></div>
        }
        else if (this.props.icon) {
            icon = <div className="icon">{this.props.icon}</div>
        }
        if (this.props.right_icon) {
            rightIcon = <div className={'pull-right icon'+(this.props.right_icon_callback ? '' : '')}
                >{this.props.right_icon}</div>
        }

        if (typeof this.state.content !== 'object' && this.state.content.indexOf('.png') != -1) {
            content = <img height="37" src={this.state.content}/>
        } else {
            contentRaw = content;
            if (this.props.classExtra && this.props.classExtra.indexOf('lg') != -1) {
                content = this.truncate(35);
            } else {
                content = this.truncate(17);
            }
        }
        return (
            <div
                className={'pull-left dark-label-wrapper '+this.props.classExtra+(this.props.right_icon_callback ? ' pointer' : '')}
                onClick={(this.props.right_icon_callback ? this.props.right_icon_callback : null)}>
                {icon}
                <div className="content">
                    {this.props.editing ?
                        <input name="labelInput" className="" onBlur={this.onBlur} autoFocus={true} value={this.state.content}
                               onChange={this.handleEditing.bind(this)}/> : content}
                </div>
                {rightIcon}
                {this.props.dropdown}
            </div>
        );
    }
}

他告诉我他在for循环之外声明someArray =......... int a; for(int i=0; i < someArray; i++) { a=someArray.get(i).length(); // Do something } 以避免频繁的垃圾收集。

我认为在for循环中声明a更具可读性和线程安全性。

但是我不能不同意如果在for循环中声明了迭代的不同实例a没有被垃圾收集。

对我有任何建议吗?

3 个答案:

答案 0 :(得分:4)

垃圾收集处理对象。你所拥有的是一个原始本地变量a,它将被分配到堆栈中。

因此,这个问题的整个前提是错误的。

答案 1 :(得分:3)

尝试反编译两个版本:

void outside(List<String> someArray) {
  // I've declared this outside the for loop too in order that the
  // the variables i and a are numbered the same in the two versions -
  // this makes no difference with respect to a.
  int i;
  int a;
  for(i=0; i < someArray.size(); i++) {
    a=someArray.get(i).length();
    // Do something
  }
}

void inside(List<String> someArray) {
  for(int i=0; i < someArray.size(); i++) {
    int a=someArray.get(i).length();
    // Do something
  }
}

结果字节码是相同的,因此没有性能或行为差异。

因此,您应该使用更易读的变量,并且变量范围更小:在循环内声明变量。

  void outside(java.util.List<java.lang.String>);
    Code:
       0: iconst_0
       1: istore_2
       2: iload_2
       3: aload_1
       4: invokeinterface #2,  1            // InterfaceMethod java/util/List.size:()I
       9: if_icmpge     32
      12: aload_1
      13: iload_2
      14: invokeinterface #3,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      19: checkcast     #4                  // class java/lang/String
      22: invokevirtual #5                  // Method java/lang/String.length:()I
      25: istore_3
      26: iinc          2, 1
      29: goto          2
      32: return

  void inside(java.util.List<java.lang.String>);
    Code:
       0: iconst_0
       1: istore_2
       2: iload_2
       3: aload_1
       4: invokeinterface #2,  1            // InterfaceMethod java/util/List.size:()I
       9: if_icmpge     32
      12: aload_1
      13: iload_2
      14: invokeinterface #3,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      19: checkcast     #4                  // class java/lang/String
      22: invokevirtual #5                  // Method java/lang/String.length:()I
      25: istore_3
      26: iinc          2, 1
      29: goto          2
      32: return

答案 2 :(得分:1)

由于a不是每次循环迭代创建的对象,因此根本不会进行垃圾回收。

int,float,bool等本地非对象数据类型保存在堆栈中。如果变量超出范围,它们将从堆栈中弹出。

如果a是一个对象,对象的引用将被删除,每次都会导致对象本身不再被引用,这意味着它将在未来的某个时刻被GCed。

更多信息:(第2.6章) https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html