我有一位朋友告诉我以下情况,但我不能说明原因。
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
没有被垃圾收集。
对我有任何建议吗?
答案 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