我对以下风格的代码进行了评论:
Iterable<String> upperCaseNames = Iterables.transform(
lowerCaseNames, new Function<String, String>() {
public String apply(String input) {
return input.toUpperCase();
}
});
Run Code Online (Sandbox Code Playgroud)
该人说,每次我通过这段代码,我都会实例化这个匿名的Function类,而我宁愿在一个静态变量中有一个实例:
static Function<String, String> toUpperCaseFn =
new Function<String, String>() {
public String apply(String input) {
return input.toUpperCase();
}
};
...
Iterable<String> upperCaseNames =
Iterables.transform(lowerCaseNames, toUpperCaseFn);
Run Code Online (Sandbox Code Playgroud)
在一个非常肤浅的层面上,这在某种程度上是有道理的; 多次实例化一个类必须浪费内存或其他东西,对吧?
另一方面,人们在代码中间实例化匿名类,就像没有明天一样,编译器优化它是微不足道的.
这是一个有效的问题吗?
有关Sun/Oracle JVM优化的有趣事实,如果您实例化一个未在线程外部传递的对象,JVM将在堆栈而不是堆上创建对象.
通常,堆栈分配与暴露内存模型的语言相关联,如C++.您不必delete在C++中堆栈变量,因为退出作用域时它们会自动释放.这与堆分配相反,堆分配要求您在完成后删除指针.
在Sun/Oracle JVM中,分析字节码以确定对象是否可以"逃避"该线程.有三个级别的逃脱:
这基本上类似于问题,1)我传递/返回它,2)我是否将它与附加到GC根的内容相关联?在您的特定情况下,匿名对象将被标记为" 无本地转义" 并将被分配到堆栈,然后通过在对不起,当我写完答案时,我并没有太多关注.它实际上是本地转义,这意味着对象上的任何锁(读取:使用for循环的每次迭代中简单地弹出堆栈来清理,因此清理它将是超快的.synchronized)都将被优化掉.(为什么要同步一些不会在另一个线程中使用的东西?)这与"无法逃避"不同,这将是在堆栈上进行分配.重要的是要注意这个"分配"与堆分配不同.它真正做的是在堆栈上为非转义对象内的所有变量分配空间.如果你有3场,int,String,和MyObject无逃生对象的内部,然后是三个堆栈变量将被分配:一int,一个String参考和MyObject借鉴.然后优化对象分配,并使用本地堆栈变量而不是堆变量运行构造函数/方法.
话虽这么说,这对我来说听起来不成熟.除非后来证明代码很慢并且导致性能问题,否则您不应该做任何事情来降低其可读性.对我来说,这段代码非常易读,我会不管它.当然,这是完全主观的,但"性能"不是改变代码的好理由,除非它与算法运行时间有关.通常,过早优化是中级编码器的指标."专家"(如果有这样的事情)只是编写更容易维护的代码.