有一个内部问题,为什么 java 匿名类不能同时实现和子类化?或者仅仅是因为语法?
5 回答
有一个内部问题,为什么 java 匿名类不能同时实现和子类化?
由于句法原因,我相信它是 99%。类型参数甚至支持交集类型( <T extends InterfaceX & InterfaceY>
),所以我认为这样的特性不会引入任何矛盾或复杂性。
例如,像这样的表达式new (InterfaceX & InterfaceY)() { ... }
可以编译成类似的东西
interface InterfaceXandY extends InterfaceX, InterfaceY {}
... new InterfaceXandY() { ... }
没有添加此类功能的原因很可能是因为它是一种罕见的用例,有一个简单的解决方法。
在一个有点相关的说明上。例如,您可以让 lambda 实现Serializable
Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");
发现了一个关于这个的黑客
在你的文件底部创建一个接口,扩展你想要实现的所有接口,然后创建一个匿名类来实现它。
仅语法,所谓的匿名类是 100% 普通类。你可以通过使用 java.lang.reflect.Proxy 和 InvocationHandler 来获得一个时髦的结果,这将是最肮脏的方法。
更简单的方法包括在方法中声明类并添加“实现”,
提供匿名类作为一种快速简洁地构建“一次性”类的方法。您的问题表明您正在尝试以多种方式使用您的匿名类(至少一个接口,一个扩展)。在这种情况下,如果您将该匿名类提升为完整类,它将更具可读性和可维护性。
这也可以通过更好地管理类的封装来避免意外的副作用。
闭包最初被排除在 Java 之外更多是因为时间压力。在 Java 的早期,缺少闭包是相当痛苦的,因此内部类诞生了:这是一种令人不安的折衷方案,它试图避免一些棘手的问题。但在许多设计问题中很正常,简化并没有真正解决任何问题,他们只是移动了它们。
有趣的是,既然 lambda 表达式和闭包被添加到 Java 中,而且这次使用了不同于内部类的东西,我们可以动态定义一个由多个接口组成的对象,前提是第二个接口是标记接口。
interface Bar {
default String getName() { return "Bar"; }
}
Object o = (Comparable<Integer> & Bar) (x,y) -> x > y ? x : y;
Bar b = (Bar) o;
System.out.println(b.getName()); //Bar
这可以在我最新的 JDK 8 版本(2013 年 3 月 12 日)中完美编译和运行。所以,看起来他们这次已经对这个问题给予了更多的思考。