gpt4 book ai didi

java - 使用匿名类有什么害处?

转载 作者:IT老高 更新时间:2023-10-28 20:50:49 25 4
gpt4 key购买 nike

在阅读此 question - How do I join two lists in java 的答案时出现了问题.这个answer给出了解决方案

List<String> newList = new ArrayList<String>() { { addAll(listOne); addAll(listTwo); } };

看了评论,用户说它邪恶丑陋,不应该在生产中使用。

我想知道使用这个有什么害处?为什么在生产中使用它是丑陋、邪恶或不好的?

最佳答案

除了已经提到的关于良好编程风格和继承滥用的问题之外,还有一个更微妙的问题 - 内部类和(非静态)匿名类实例充当闭包。这意味着它们保留对封闭类实例的隐式引用。这可能会导致阻止垃圾收集,最终导致内存泄漏。

给出一个示例源代码:

public interface Inner {
void innerAction();
}

public class Outer {

public void methodInOuter() {}

private Inner inner = new Inner() {
public void innerAction() {
// calling a method outside of scope of this anonymous class
methodInOuter();
}
}
}

编译时发生的事情是,编译器为 Inner 的新匿名子类创建一个类文件,该类文件获取一个所谓的合成字段,并引用 的实异常(exception)部 类。生成的字节码大致相当于这样:

public class Outer$1 implements Inner {

private final Outer outer; // synthetic reference to enclosing instance

public Outer$1(Outer outer) {
this.outer = outer;
}

public void innerAction() {
// the method outside of scope is called through the reference to Outer
outer.methodInOuter();
}
}

这种对封闭实例的引用的捕获甚至发生在从未实际访问封闭类的任何方法或字段的匿名类中,例如您的双括号初始化 (DBI) 列表问题。

这导致 DBI 列表只要存在就保留对封闭实例的引用,从而防止封闭实例被垃圾收集。假设 DBI 列表恰好在应用程序中存在很长时间,例如作为 MVC 模式中模型的一部分,并且捕获的封闭类例如是一个 JFrame,这是一个相当大的有很多领域的类。如果您创建了几个 DBI 列表,您很快就会发生内存泄漏。

一种可能的解决方案是仅在 静态 方法中使用 DBI,因为在它们的范围内没有可用的封闭实例。

另一方面,我仍然认为在大多数情况下仍然没有必要使用 DBI。至于列表加入,我会创建一个简单的可复用方法,不仅更安全,而且更简洁明了。

public static <T> List<T> join(List<? extends T> first, List<? extends T> second) {
List<T> joined = new ArrayList<>();
joined.addAll(first);
joined.addAll(second);
return joined;
}

然后客户端代码就变得简单了:

List<String> newList = join(listOne, listTwo);

进一步阅读: https://stackoverflow.com/a/924536/1064809

关于java - 使用匿名类有什么害处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16397027/

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