gpt4 book ai didi

java - 重复实例化匿名类是否浪费?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:57:06 26 4
gpt4 key购买 nike

我对一段代码的评论是这样的:

Iterable<String> upperCaseNames = Iterables.transform(
lowerCaseNames, new Function<String, String>() {
public String apply(String input) {
return input.toUpperCase();
}
});

那个人说每次我浏览这段代码时,我都会实例化这个匿名函数类,我宁愿在静态变量中有一个实例:

static Function<String, String> toUpperCaseFn =
new Function<String, String>() {
public String apply(String input) {
return input.toUpperCase();
}
};
...
Iterable<String> upperCaseNames =
Iterables.transform(lowerCaseNames, toUpperCaseFn);

从表面上看,这在某种程度上是有道理的;多次实例化一个类肯定会浪费内存什么的,对吧?

另一方面,人们在代码中间实例化匿名类就像没有明天一样,编译器优化它是微不足道的。

这是一个合理的担忧吗?

最佳答案

关于 Hot Spot JVM 优化的有趣事实,如果您实例化一个未在当前方法之外传递的对象,JVM 将在字节码级别执行优化。

通常,堆栈分配与公开内存模型的语言相关联,例如 C++。您不必在 C++ 中delete 堆栈变量,因为它们会在作用域退出时自动释放。这与堆分配相反,堆分配要求您在使用完指针后将其删除。

在 Hot Spot JVM 中,分析字节码以确定对象是否可以“逃离”线程。有three levels of escape :

  1. 无转义 - 该对象仅在其创建的方法/范围内使用,不能在线程外访问该对象。
  2. Local/Arg escape - 对象由创建它的方法返回或传递给它调用的方法,但这些方法都不会将该对象放在可以在线程外访问的地方。
  3. 全局转义 - 对象被放置在可以在另一个线程中访问的地方。

这基本上类似于以下问题:1) 我是否将它传递给另一个方法或返回它,以及 2) 我是否将它与附加到 GC 根的某些东西相关联,例如 ClassLoader 或其他东西存储在 static 字段中?

在您的特定情况下,匿名对象将被标记为“本地转义”,这仅意味着对象上的任何锁(读取:同步 的使用)将被优化掉。 (为什么要在另一个线程中永远不会使用的东西上进行同步?)这与“无逃逸”不同,后者在堆栈上进行分配。请务必注意,此“分配”与堆分配不同。它真正做的是在堆栈上为非转义对象内的所有变量分配空间。如果在 no-escape 对象中有 3 个字段,intStringMyObject,那么将分配三个堆栈变量:一个 int,一个 String 引用,和一个 MyObject referenceMyObject 实例本身将仍然存储在堆中,除非它也被分析为“无法逃脱”。然后优化对象分配,构造函数/方法将使用本地堆栈变量而不是堆变量运行。

话虽这么说,但对我来说这听起来像是过早的优化。除非代码后来被证明速度很慢并且导致性能问题,否则您不应该做任何事情来降低它的可读性。对我来说,这段代码可读性很强,我不会管它。当然,这完全是主观的,但是“性能”不是更改代码的好理由,除非它与实际运行时间有关。通常,过早的优化会导致代码更难维护,性能优势微乎其微。

Java 8+ 和 Lambdas

如果分配匿名实例仍然困扰您,我建议您改用 Lambdas 来处理单一抽象方法 (SAM) 类型。 Lambda 评估是使用 invokedynamic 执行的,并且实现最终在第一次调用时仅创建 Lambda 的单个实例。可以找到更多详细信息in my answer herethis answer here .对于非 SAM 类型,您仍然需要分配一个匿名实例。在大多数用例中,这里的性能影响可以忽略不计,但在我看来,这种方式更具可读性。

引用资料

关于java - 重复实例化匿名类是否浪费?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19718353/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com