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


当前回答

似乎这里没有人提到,但你也可以使用匿名类来保存泛型类型参数(通常由于类型擦除而丢失):

public abstract class TypeHolder<T> {
    private final Type type;

    public TypeReference() {
        // you may do do additional sanity checks here
        final Type superClass = getClass().getGenericSuperclass();
        this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    }

    public final Type getType() {
        return this.type;
    }
}

如果你用匿名的方式实例化这个类

TypeHolder<List<String>, Map<Ineger, Long>> holder = 
    new TypeHolder<List<String>, Map<Ineger, Long>>() {};

然后,这样的holder实例将包含传递类型的非擦除定义。

使用

这对于构建验证器/反序列化器非常方便。此外,您还可以使用反射实例化泛型类型(因此,如果您想在参数化类型中执行新的T()—欢迎您!)

不便/限制

您应该显式地传递泛型参数。如果不这样做,将导致类型参数丢失 每次实例化都会花费编译器生成额外的类,这会导致类路径污染/jar膨胀

其他回答

是的,匿名内部类绝对是Java的优势之一。

使用匿名内部类,您可以访问周围类的final变量和成员变量,这在侦听器等方面很方便。

但是一个主要的优点是,内部类代码(至少应该)与周围的类/方法/块紧密耦合,具有特定的上下文(周围的类、方法和块)。

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

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

它们通常用作详细形式的回调。

我想你可以说,与没有它们和每次都必须创建命名类相比,它们是一个优势,但类似的概念在其他语言中实现得更好(如闭包或块)。

下面是一个swing的例子

myButton.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        // do stuff here...
    }
});

尽管它仍然很冗长,但它比强迫您为每个throw away侦听器定义一个命名类要好得多(尽管这取决于情况和重用,这可能仍然是更好的方法)

所谓的“匿名类”,我想你是指匿名的内部类。

匿名内部类在创建具有某些“额外”(如重写方法)的对象实例时非常有用,而不必实际继承一个类。

我倾向于使用它作为附加事件监听器的快捷方式:

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // do something
    }
});

使用这个方法可以使编码更快一点,因为我不需要创建一个额外的实现ActionListener的类——我可以实例化一个匿名的内部类,而不需要实际创建一个单独的类。

我只在“快速而肮脏”的任务中使用这种技巧,让整个类感觉没有必要。拥有多个做完全相同事情的匿名内部类应该被重构为一个实际的类,无论是内部类还是单独的类。

匿名类在类终结中的主要用法之一叫做终结器守护者。在Java世界中,应该避免使用finalize方法,除非你真的需要它们。你必须记住,当你重写子类的finalize方法时,你也应该总是调用super.finalize(),因为超类的finalize方法不会自动调用,你可能会遇到内存泄漏的问题。

所以考虑到上面提到的事实,你可以像这样使用匿名类:

public class HeavyClass{
    private final Object finalizerGuardian = new Object() {
        @Override
        protected void finalize() throws Throwable{
            //Finalize outer HeavyClass object
        }
    };
}

使用这种技术,您可以让自己和其他开发人员在需要finalize方法的重量级类的每个子类上调用super.finalize()。