在Java中匿名类有什么用?我们可以说使用匿名类是Java的优点之一吗?
当前回答
匿名内部类用于创建一个永远不会被再次引用的对象。它没有名称,在同一个语句中声明和创建。 这用于通常使用对象变量的地方。用new关键字替换变量,调用构造函数和{and}内的类定义。
当用Java编写线程程序时,它通常是这样的
ThreadClass task = new ThreadClass();
Thread runner = new Thread(task);
runner.start();
这里使用的ThreadClass是用户定义的。该类将实现创建线程所需的Runnable接口。在ThreadClass中run()方法(Runnable中唯一的方法)也需要实现。 显然,去掉ThreadClass会更有效,这正是匿名内部类存在的原因。
请看下面的代码
Thread runner = new Thread(new Runnable() {
public void run() {
//Thread does it's work here
}
});
runner.start();
这段代码替换了最上面的示例中对任务的引用。Thread()构造函数中的匿名内部类并没有单独的类,而是返回一个未命名的对象,该对象实现了Runnable接口并重写了run()方法。方法run()将包含执行线程所需工作的语句。
在回答“匿名内部类是否是Java的优点之一”这个问题时,我不得不说我不太确定,因为目前我对许多编程语言都不熟悉。但我能说的是,这绝对是一种更快更简单的编码方法。
参考资料:山姆自学Java在21天第七版
其他回答
您可以在需要在另一个函数中为特定目的创建类的情况下使用它,例如,作为侦听器,作为可运行对象(生成线程)等。
其思想是,从函数代码内部调用它们,因此永远不会在其他地方引用它们,因此不需要命名它们。编译器只是枚举它们。
它们本质上是语法糖,当它们变大时通常应该转移到其他地方。
我不确定这是否是Java的优点之一,但如果您确实使用它们(不幸的是,我们都经常使用它们),那么您可能会认为它们是优点之一。
匿名类指南。
匿名类同时声明和初始化。 匿名类必须扩展或实现到一个且仅一个类或接口响应。 由于匿名类没有名称,所以只能使用一次。
例如:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});
我有时使用它们作为Map实例化的语法hack:
Map map = new HashMap() {{
put("key", "value");
}};
vs
Map map = new HashMap();
map.put("key", "value");
它在执行大量put语句时节省了一些冗余。然而,当外部类需要通过远程序列化时,我也遇到了这样做的问题。
内部类与外部类的实例相关联,有两种特殊类型:局部类和匿名类。匿名类使我们能够同时声明和实例化一个类,从而使代码简洁。当我们只需要一个本地类一次时,我们使用它们,因为它们没有名字。
考虑一下文档中的例子,我们有一个Person类:
public class Person {
public enum Sex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress;
public int getAge() {
// ...
}
public void printPerson() {
// ...
}
}
我们有一个方法来打印匹配搜索条件的成员:
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
其中CheckPerson是一个像这样的接口:
interface CheckPerson {
boolean test(Person p);
}
现在我们可以使用匿名类来实现这个接口来指定搜索条件:
printPersons(
roster,
new CheckPerson() {
public boolean test(Person p) {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
}
);
这里的接口非常简单,而且匿名类的语法看起来笨拙而不清楚。
Java 8引入了一个术语函数接口,它是一个只有一个抽象方法的接口,因此我们可以说CheckPerson是一个函数接口。我们可以使用Lambda表达式,它允许我们将函数作为方法参数传递给:
printPersons(
roster,
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
我们可以使用标准功能接口Predicate来代替接口CheckPerson,这将进一步减少所需的代码量。
您可以这样使用匿名类
TreeSet treeSetObj = new TreeSet(new Comparator()
{
public int compare(String i1,String i2)
{
return i2.compareTo(i1);
}
});
推荐文章
- Java 8接口方法中不允许“同步”的原因是什么?
- 如何找到Java堆大小和内存使用(Linux)?
- 使用Enum实现单例(Java)
- RabbitMQ与通道和连接之间的关系
- buildSessionFactory()配置方法在Hibernate中已弃用?
- Spring MVC -如何获得所有的请求参数在一个地图在Spring控制器?
- 如何在Java中按两个字段排序?
- 文件之间的差异。路径中的分隔符和斜杠
- 在方法参数中使用NotNull注释
- Spring MVC中处理可选参数的@RequestParam
- Tomcat:如何查找正在运行的Tomcat版本?
- “java”、“javaw”和“javaws”之间有什么区别?
- 将Date对象转换为日历对象
- 在Java中保存最后N个元素的大小有限的队列
- 如何运行一个类从Jar不是主类在其清单文件