Answers:
上例中的static关键字是多余的(嵌套接口自动为“ static”),可以删除而不会影响语义;我建议将其删除。接口方法上的“公共”和接口字段上的“公共最终”也是如此-修饰符是多余的,只会给源代码增加混乱。
无论哪种方式,开发人员都只是声明一个名为Foo.Bar的接口。与封闭类没有进一步的关联,除了无法访问Foo的代码也将无法访问Foo.Bar。(从源代码开始,即使Foo是程序包私有的,字节码或反射也可以访问Foo.Bar!)
如果希望只在外部类中使用嵌套接口,则可以采用这种方式创建嵌套接口,这样您就不必创建新的顶级名称。例如:
public class Foo {
public interface Bar {
void callback();
}
public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
public void callback() {...}
});
已经回答了这个问题,但是使用嵌套接口的一个很好的理由是,其嵌套函数是否与其所在的类直接相关。一个很好的例子是Listener
。如果您有一个类,Foo
并且希望其他类能够侦听其上的事件,则可以声明一个名为的接口FooListener
,这没关系,但是声明一个嵌套的接口并让其他类实现Foo.Listener
(嵌套类Foo.Event
也不错)。
java.util.Map.Entry
(嵌套在另一个接口中的一个接口)。
Map.Entry
)或类也都应包含在该包中。我之所以这样说,是因为我喜欢保持课堂简短。读者还可以通过查看包中的类来查看与该类相关的其他实体。我可能会有一个java.collections.map
地图包。这与面向对象和模块化有关。java.util
里面太多了。util
就像common
-有气味的IMO
java.util
当然里面有太多东西。就是说,我也不认为将其分解为您建议的如此细粒度的软件包也是理想的。
java.util.MapEntry
在自己的程序包之外调用此接口。第一反应:与此类相关的接口是什么?我看着课。除非javadoc链接到此接口,否则我不知道它们之间的关系。而且人们不会看进口包装。每个人都有自己的意见。没有人是对的,没有人是错的
成员接口是隐式静态的。您可以删除示例中的static修饰符,而无需更改代码的语义。另请参见Java语言规范8.5.1。静态成员类型声明
内部接口必须是静态的才能被访问。该接口与该类的实例无关,但与该类本身相关联,因此可以通过进行访问Foo.Bar
,如下所示:
public class Baz implements Foo.Bar {
...
}
在大多数情况下,这与静态内部类没有什么不同。
The interface isn't associated with instances of the class, but with the class itself
进一步解释什么,我没明白
Jesse的答案很接近,但是我认为有更好的代码来说明为什么内部接口可能有用。在继续阅读之前,请看下面的代码。您能找到为什么内部接口有用吗?答案是,可以使用实现A和C的任何类实例化DoSomethingAlready 类。不只是具体的动物园。当然,即使AC不是内部的,也可以实现,但是想像一下将更长的名称(不仅是A和C)串联起来,然后将其用于其他组合(例如A和B,C和B等),您就可以轻松实现看看事情如何失控。更不用说审查您的源代码树的人会被仅在一类中有意义的界面所淹没。因此,总而言之,内部接口可以构造自定义类型并改进其封装。
class ConcreteA implements A {
:
}
class ConcreteB implements B {
:
}
class ConcreteC implements C {
:
}
class Zoo implements A, C {
:
}
class DoSomethingAlready {
interface AC extends A, C { }
private final AC ac;
DoSomethingAlready(AC ac) {
this.ac = ac;
}
}
Zoo
也没有实现接口AC
,因此,实例Zoo
不能被传递到的构造DoSomethingAlready
,其预期AC
。AC
扩展A
和的事实C
并不意味着类也可以实现A
,C
也可以魔术地实现AC
。
1998年,Philip Wadler提出了静态接口和非静态接口之间的区别。
据我所知,使接口成为非静态接口的唯一区别是它现在可以包括非静态内部类。因此更改不会使任何现有Java程序无效。
例如,他提出了表达问题的解决方案,即一方面表达为“您的语言可以表达多少”与另一方面表达为“您要用语言表达的术语”之间的不匹配。
静态和非静态嵌套接口之间的区别的示例可以在他的示例代码中看到:
// This code does NOT compile
class LangF<This extends LangF<This>> {
interface Visitor<R> {
public R forNum(int n);
}
interface Exp {
// since Exp is non-static, it can refer to the type bound to This
public <R> R visit(This.Visitor<R> v);
}
}
他的建议从未在Java 1.5.0中实现。因此,所有其他答案都是正确的:静态和非静态嵌套接口没有区别。
在Java中,静态接口/类允许接口/类的使用像顶级类一样,也就是说,它可以由其他类声明。因此,您可以执行以下操作:
class Bob
{
void FuncA ()
{
Foo.Bar foobar;
}
}
没有静态,以上内容将无法编译。这样做的好处是,您不需要新的源文件即可声明接口。由于必须编写Foo.Bar,因此它还可视化地将Bar接口与Foo类关联,并暗示Foo类对Foo.Bar实例进行了某些操作。
静态意味着包(项目)的任何类部分都可以访问它而无需使用指针。根据情况,这可能有用或受阻。
Math类是“静态”方法有用的完美示例。Math中的所有方法都是静态的。这意味着您不必费力地创建新实例,声明变量并将它们存储在更多变量中,您只需输入数据即可获得结果。
静态并不总是那么有用。例如,如果要进行案例比较,则可能需要以几种不同的方式存储数据。您不能创建三个具有相同签名的静态方法。您需要3个不同的实例(非静态),然后可以进行比较,如果是静态的,则数据不会随输入而改变。
静态方法适合一次性返回和快速计算或轻松获得数据。