EventListener
或Runnable
这样的受限条件外。他们甚至在我第一个工业项目中被“禁止”使用。这是否真的是最佳实践?为什么?(我必须说我经常使用它们...)
--编辑---
我不能在所有这些回复中选出正确答案:几乎所有回复都有一定程度的正确性:我仍然会使用内部类,但我会尽量少用!
EventListener
或Runnable
这样的受限条件外。他们甚至在我第一个工业项目中被“禁止”使用。这是否真的是最佳实践?为什么?我认为,在Java代码中,90%的内部类要么是与单个类相关联的实体,因此作为内部类“塞进去”的,要么是由于Java不支持Lambda而存在的匿名内部类。
我个人不喜欢看到复杂的内部类。它们增加了源文件的复杂性,使其变得更大,在调试和分析方面处理起来很麻烦等等。我喜欢将我的项目分成许多包,在这种情况下,我可以将大多数实体作为仅限于该包的顶级类。
这留下了一些必要的内部类,例如动作监听器、虚假的“函数”编程等等。它们通常是匿名的,虽然我不是粉丝(在许多情况下更喜欢Lambda),但我能接受它们但不喜欢它们。
我已经好几年没做过C#了,但我想知道当他们引入Lambda时,内部类或C#等效物的普及率是否会降低。
代码整洁化。如果将代码分成逻辑上的部分,而不是全部混在同一个文件中,那么它更容易被理解。
话虽如此,我认为明智地使用内部类并不是不恰当的。有时这些内部类只存在于一个目的中,因此我就不会对它们存在于唯一使用它们的文件中感到困扰。然而,在我的经验中,这种情况并不经常发生。
是的,禁止使用内部类是一种有用的做法,因为发现一个地方禁止使用它们是警告我不要在那里工作的好方法,从而保护我的未来健康。 :)
正如gicappa指出的那样,匿名内部类是Java最接近闭包的方式,并且非常适合在需要将行为传递到方法中的情况下使用,如果没有其他更好的选择。
正如其他人所说,当你使用匿名内部类时,它也会在其他地方使用...
因此,您可能会将内部类代码轻松地复制到许多地方... 当您仅使用非常简单的内部类来过滤/排序集合时,使用谓词、比较器或类似方法似乎不是问题...
但是,您必须知道,当您三次使用匿名内部类来执行完全相同的操作(例如从集合中删除“”),您实际上正在创建3个新类于Java PermGen中。
因此,如果每个人都在各处使用内部类,则可能导致应用程序具有更大的PermGen。根据应用程序,这可能是一个问题...如果您正在工业界工作,则可能编写具有有限内存且需要优化的嵌入式应用程序...
请注意,这也是为什么双大括号语法(具有非静态初始化块的匿名内部类)有时被认为是反面模式的原因之一:
new ArrayList<String>() {{
add("java");
add("jsp");
add("servlets");
}}
如果有人禁止你使用它们,你应该询问他们的原因......在我看来,这完全取决于上下文......
如果需要一个方法参数,我建议在使用它时要谨慎。我刚刚发现了与此相关的内存泄漏问题。这涉及到HttpServlet使用GrizzlyContinuation。
简而言之,以下是有缺陷的代码:
public void doGet(HttpServletRequest request, final HttpServletResponse response){
createSubscription(..., new SubscriptionListener(){
public void subscriptionCreated(final CallController controller) {
response.setStatus(200);
...
controller.resume();
}
public void subscriptionFailed(){
...
}
public void subscriptionTimeout(){
...
}});
}
这里没有提到的一件事是,(非静态)内部类拥有对其封闭类的引用。更重要的是,内部类可以访问其封闭类的私有成员。这可能会破坏封装性。
如果有选择,请不要使用内部类。
bagOfStuff = new HashSet(){
@Override
public boolean add(Object o) {
boolean returnValue = super.add(o);
if(returnValue && o instanceof Job)
{
Job job = ((Job)o);
if(job.fooBar())
otherBagOfStuff.add(job);
}
return returnValue;
}
}