在Java中匿名类有什么用?我们可以说使用匿名类是Java的优点之一吗?


当前回答

内部类与外部类的实例相关联,有两种特殊类型:局部类和匿名类。匿名类使我们能够同时声明和实例化一个类,从而使代码简洁。当我们只需要一个本地类一次时,我们使用它们,因为它们没有名字。

考虑一下文档中的例子,我们有一个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的优点之一,但如果您确实使用它们(不幸的是,我们都经常使用它们),那么您可能会认为它们是优点之一。

我有时使用它们作为Map实例化的语法hack:

Map map = new HashMap() {{
   put("key", "value");
}};

vs

Map map = new HashMap();
map.put("key", "value");

它在执行大量put语句时节省了一些冗余。然而,当外部类需要通过远程序列化时,我也遇到了这样做的问题。

还有一个好处: 正如你所知道的,Java不支持多重继承,所以如果你使用“线程”类作为匿名类,那么类仍然有一个空间留给任何其他类来扩展。

匿名内部类用于以下场景:

1)。对于重写(子类化),当类定义除当前情况外不可用时:

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.) 参数定义匿名内部类:

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");
            } 
        });
    } 
}