我知道在实现Listener和类似的东西时,匿名类可以保存输入。他们试图成为一些封闭用法的替代品。
但社区对这种语言功能的价值有何看法?它是否有意义并且您经常使用它吗?它是否使代码更清晰,更易理解,更易于维护?或者匿名类使代码的可读性降低?
您有什么看法,请举例说明/支持您的意见?
答案 0 :(得分:29)
我倾向于使用匿名内部类,在我不需要完成一个完整的类来执行某些任务的情况下。例如,如果我想实现ActionListener
或Runnable
,但我认为不需要内部类。例如,对于启动简单的Thread
,使用匿名内部类可能更具可读性:
public void someMethod()
{
new Thread(new Runnable() {
public void run()
{
// do stuff
}
}).start();
}
在某些情况下,例如上面的示例,它可以提高可读性,尤其是对于一次性任务,因为要执行的代码全部写在一个位置。使用内部类将“非本地化”代码:
public void someMethod()
{
new Thread(new MyRunnable()).start();
}
// ... several methods down ... //
class MyRunnable implements Runnable
{
public void run()
{
// do stuff
}
}
然而,如果说有可能会重复相同的事情,那么它确实应该是一个单独的类,无论是常规类还是内部类。
我倾向于在程序中使用匿名内部类,我只是尝试解决问题而不是将其作为实际应用程序的核心功能。
答案 1 :(得分:12)
匿名内部类的另一个好用途是当你需要初始化像ArrayList和Set这样的集合时。这种做法也称为双支撑初始化 例如,
private static final Set<String> VALID_CODES = new HashSet<String>() {{
add("XZ13s");
add("AB21/X");
add("YYLEX");
add("AR2D");
}};
显然,这不仅限于收藏品;它可以用来初始化任何类型的对象 - 例如Gui对象:
add(new JPanel() {{
setLayout(...);
setBorder(...);
add(new JLabel(...));
add(new JSpinner(...));
}});
答案 2 :(得分:11)
我的观点是匿名类使代码的可读性降低。为了实现监听器,匿名类很有用。对于开发GWT应用程序,匿名类是更好的选择。 对于这些情况,如果我们不使用匿名类,则代码行数将增加。
答案 3 :(得分:6)
我们重新使用匿名类。我发现它们很容易用于实现只有一个或两个方法的接口,以及在其他任何地方使用 功能的接口。如果你在其他地方再次使用相同的功能,那么应该有一个真正的类可以重用。
答案 4 :(得分:4)
使用匿名类改善或降低易读性是一个品味问题。主要问题绝对不在这里。
匿名类,如内部类,带有对封闭类的引用,从而使得没有它的非私有事物。简而言之,封闭类的 this 引用可以通过内部类来逃避。所以答案是:如果内部类是自己发布的,那么使用它是一种非常糟糕的做法,因为它会自动发布封闭类。例如:
changeManager.register(new ChangeListener() {
public void onChange(...) {
...
}});
此处,匿名 ChangeLstener 会传递到 ChangeManager 的注册方法。这样做也会自动发布封闭类。
这绝对是一种不好的做法。
答案 5 :(得分:3)
我主要使用匿名类来处理只有一种方法的接口,即Runnable或ActionListener。大多数较大的接口都会在已有的类中更新自己的类或实现。因为我认为我不需要支持它的论据。
答案 6 :(得分:2)
匿名类主要出现在GUI应用程序中,专门用于事件处理。在实现包含一个或两个方法的小接口的情况下,匿名类很有用。例如..你有一个类,你有两个或三个线程,您希望使用这些线程执行两个或三个不同的任务。在这种情况下,您可以借助匿名类来执行所需的任务。看下面的例子
class AnonymousClass{
public static void main(String args[]){
Runnable run1=new Runnable(){
public void run(){
System.out.println("from run1");
}
};
Runnable run2=new Runnable(){
public void run(){
System.out.println("from run2");
}
};
Runnable run3=new Runnable(){
public void run(){
System.out.println("from run3");
}
};
Thread t1=new Thread(run1);
Thread t2=new Thread(run2);
Thread t3=new Thread(run3);
t1.run();t2.run();t3.run();
}
}
输出:
来自run1
来自run2
来自run3
在上面的代码快照中,我使用了三个线程来执行三个不同的任务。看,我创建了三个匿名类,其中包含执行三种不同小任务的run方法的实现。
答案 7 :(得分:1)
使用它们是有道理的,但你必须知道在底层做什么。我只使用它们,如果我需要一个类来做一些我不需要的其他特定的东西。
答案 8 :(得分:1)
这取决于你比较它们。我宁愿拥有它们而不是拥有它们,但是我宁愿能够为像Arrays.sort()这样的方法提供简单的代码块,而不是必须显式创建一个包含我的compare()实现的类。
答案 9 :(得分:1)
如果尽可能限制范围和访问权限是件好事,那么匿名类就非常好。它们的范围有限于需要它们的一个类。如果合适,我会说匿名课程很好。
你复制相同功能的那一刻,它就变成了一个坏主意。将其重构为一个独立的公共类。具有重构功能的IDE可以轻松实现。
答案 10 :(得分:0)
匿名类没有任何本质上的不同或特殊之处。它们最终只是语法糖,支持引用外部类。这使得编写适配器变得更容易 - 就像Collections框架返回的大多数Iterator实现一样。
答案 11 :(得分:0)
我主要使用匿名类 a)简写符号,如果接口有一个或两个方法,并且它不会影响可读性
b)我无法证明创建新类的情况,例如,当你必须附加一个actionlistner来让一个JButton进行一些简单的操作时,就可以了。
答案 12 :(得分:0)
我同意许多其他人所说的,只使用一次它们对小型界面很有用。但是我还要添加限制,如果必须更改匿名类外部的代码才能使其工作,那么不要使用匿名类。
如果必须开始将变量声明为final以容纳anon类,因为它引用它们,那么请使用内部类。我还看到一些不好的代码气味,其中最终数组(大小为1)用于返回anon类的结果。
答案 13 :(得分:0)
匿名课程不要&#34;隐藏&#34;代码,但他们做TEND,使其可重复性稍差。请注意,这也适用于闭包。
在某些方面,它们允许一些很好的重构,因为你可以将代码传递给方法。这可以非常有效地用于减少重复,我当然不会反对匿名类/闭包,但是在某些情况下它们可能是一个缺点。
首先考虑您传入的匿名内部类代码不适合在代码中重用。如果你在其他一些代码中做同样的事情,你必须将它重新编写为匿名内部类以外的东西才能重用它,在这一点上甚至可能很难知道有代码在其他地方重用。
由于缺乏重用是参数化的难点,这导致了我最大的抱怨......他们倾向于复制和粘贴代码。
我已经看过很多GUI,其中某人以匿名内部类作为事件响应者开始。许多人必须做一些稍微不同的事情,例如,5行代码,其中唯一的区别是中间的字符串。一旦你习惯使用内部类,简单的解决方案就是复制并粘贴块并替换该字符串。
创建新的&#34;命名&#34;的解决方案具有字符串参数并将该类传递给所有方法的类很少发生在该点的某个人身上。这个命名类可以使用参数或继承来定义不同的行为和代码。
我是一个关闭的粉丝,不讨厌匿名课 - 只是指出了我曾经看到过的一些陷阱。
答案 14 :(得分:0)
因此,借助接口中static
方法的Java 8新功能,您可以使用匿名内部类返回接口的实例。例如:
interface Person {
String getName();
int getAge();
static Person newInstance() {
return new Person() {
public String getName() {
return "Bob";
}
public int getAge() {
return 99;
}
}
}
}
您可以获得类似的实例:
Person person = Person.newInstance();
基本上,这允许您界面的单个默认实现。