Java中匿名类的用途是什么?我们可以说匿名类的使用是Java的优势之一吗?
通过"匿名课程",我认为你的意思是匿名的内部课程.
当创建具有某些"额外"的对象的实例(例如重写方法)时,匿名内部类可以变得有用,而不必实际上对类进行子类化.
我倾向于使用它作为附加事件监听器的快捷方式:
button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // do something } });
使用这种方法可以使编码更快一点,因为我不需要创建一个实现的额外类ActionListener
- 我可以实例化一个匿名内部类而不实际创建一个单独的类.
我只使用这种技术进行"快速而肮脏"的任务,使整个班级感觉不必要.拥有多个完全相同的匿名内部类应该重构为实际的类,无论是内部类还是单独的类.
匿名内部类是有效的闭包,因此它们可以用于模拟lambda表达式或"委托".例如,使用此界面:
public interface F { B f(A a); }
您可以匿名使用它来创建Java中的第一类函数.假设您有以下方法返回给定列表中第一个大于i的数字,或者如果没有数字更大则返回i:
public static int larger(final Listns, final int i) { for (Integer n : ns) if (n > i) return n; return i; }
然后你有另一种方法返回给定列表中小于i的第一个数字,或者如果没有数字更小则返回i:
public static int smaller(final Listns, final int i) { for (Integer n : ns) if (n < i) return n; return i; }
这些方法几乎完全相同.使用第一类函数类型F,我们可以将这些重写为一个方法,如下所示:
public staticT firstMatch(final List ts, final F f, T z) { for (T t : ts) if (f.f(t)) return t; return z; }
您可以使用匿名类来使用firstMatch方法:
FgreaterThanTen = new F { Boolean f(final Integer n) { return n > 10; } }; int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);
这是一个非常人为的例子,但很容易看出能够传递函数就像它们是值一样是一个非常有用的功能.请参阅Joel本人的"您的编程语言能做到这一点".
用这种风格编写Java的很好的库:Functional Java.
匿名内部类用于以下场景:
1.)对于Overriding(子类),当除了当前情况之外的类定义不可用时:
class A{ public void methodA() { System.out.println("methodA"); } } class B{ A a = new A() { public void methodA() { System.out.println("anonymous methodA"); } }; }
2.)为了实现接口,只有当前情况需要实现接口时:
interface interfaceA{ public void methodA(); } class B{ interfaceA a = new interfaceA() { public void methodA() { System.out.println("anonymous methodA implementer"); } }; }
3.)Argument Defined匿名内部类:
interface Foo { void methodFoo(); } class B{ void do(Foo f) { } } class A{ void methodA() { B b = new B(); b.do(new Foo() { public void methodFoo() { System.out.println("methodFoo"); } }); } }
我有时使用它们作为Map实例化的语法黑客:
Map map = new HashMap() {{ put("key", "value"); }};
VS
Map map = new HashMap(); map.put("key", "value");
在执行大量put语句时,它可以节省一些冗余.但是,当外部类需要通过远程处理序列化时,我也遇到了问题.
它们通常用作冗长的回调形式.
我想你可以说它们比没有它们更有优势,并且每次都必须创建一个命名类,但类似的概念在其他语言中实现得更好(如闭包或块)
这是一个摆动的例子
myButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { // do stuff here... } });
虽然它仍然很冗长,但它比强迫你为每个扔掉的监听器定义一个命名类要好得多(尽管取决于情况和重用,这可能仍然是更好的方法)
您可以在需要在另一个函数内为特定目的创建类的情况下使用它,例如,作为侦听器,作为runnable(以生成线程)等.
这个想法是你从一个函数的代码中调用它们,所以你永远不会在别处引用它们,所以你不需要命名它们.编译器只是枚举它们.
它们基本上是语法糖,并且通常应该随着它们变大而移动到其他地方.
我不确定它是否是Java的优势之一,但如果你确实使用它们(不幸的是我们经常使用它们),那么你可以说它们是一体的.
匿名类的GuideLines.
匿名类是同时声明和初始化的.
匿名类必须扩展或实现一个且只能实现一个类或接口.
由于anonymouse类没有名称,因此只能使用一次.
例如:
button.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub } });
是的,匿名内部类绝对是Java的优点之一。
使用匿名内部类,您可以访问周围类的final和member变量,这在侦听器等中很方便。
但是一个主要的优点是(至少应该)紧密耦合到周围的类/方法/块的内部类代码具有特定的上下文(周围的类,方法和块)。
new Thread() { public void run() { try { Thread.sleep(300); } catch (InterruptedException e) { System.out.println("Exception message: " + e.getMessage()); System.out.println("Exception cause: " + e.getCause()); } } }.start();
这也是使用线程的匿名内部类型的示例之一