mtk*_*mtk 36 java anonymous-class
在阅读这个问题的答案时出现了这个问题 - 如何在java中加入两个列表.这个答案给出了解决方案
List<String> newList = new ArrayList<String>() { { addAll(listOne); addAll(listTwo); } };
Run Code Online (Sandbox Code Playgroud)
阅读评论,用户说它是邪恶和丑陋的,不应该用于生产.
我想知道使用它有什么害处?为什么在生产中使用它是丑陋的,邪恶的还是坏的?
注意:被问到这是一个问题因为,引用的帖子太旧了(2008年),回答者几个月后就离开了.
Nat*_*tix 49
除了已经提到的关于良好编程风格和继承滥用的问题之外,还有一个更微妙的问题 - 内部类和(非静态)匿名类实例充当闭包.这意味着它们保持对封闭类实例的隐式引用.这可以防止垃圾收集,最终导致内存泄漏.
给出一段示例源代码:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在编译时发生的是,编译器为新的匿名子类创建一个类文件,该子类Inner获得一个所谓的合成字段,其中包含对该Outer类实例的引用.生成的字节码大致相当于这样的东西:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
即使对于从未实际访问封闭类的任何方法或字段的匿名类,例如您的问题中的双括号初始化(DBI)列表,也会发生对封闭实例的引用的捕获.
这导致DBI列表保留对封闭实例的引用,只要它存在,从而防止封闭实例被垃圾收集.假设DBI列表恰好在应用程序中存在了很长时间,例如作为MVC模式中模型的一部分,并且捕获的封闭类是例如a 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;
}
Run Code Online (Sandbox Code Playgroud)
然后客户端代码变得简单:
List<String> newList = join(listOne, listTwo);
Run Code Online (Sandbox Code Playgroud)
进一步阅读:https: //stackoverflow.com/a/924536/1064809
das*_*ght 19
"丑陋"和"不在生产中使用"注释指的是匿名类的这种特定用法,而不是一般的匿名类.
这个特定的用法分配newList了一个匿名子类ArrayList<String>,一个全新的类,它是为了一个目的而创建的 - 即用两个特定列表的内容初始化一个列表.这不是非常易读(即使是经验丰富的读者也会花费几秒钟来解决它),但更重要的是,它可以在没有子类化的情况下实现相同数量的操作.
从本质上讲,该解决方案为创建新子类带来了一些小便利,这可能会导致问题,例如,当您尝试使用期望集合具有特定类型的自动化框架来持久保存此集合时.
Joa*_*uer 16
这种匿名类的特殊用法有几个问题:
ArrayList,你只需要一些包含一些现有值的数组列表joinLists(listOne, listTwo))在我看来,#1是避免它的最重要原因,紧随其后的是#2.#3通常不是一个问题,但不应该被遗忘.