题
我刚刚发现了一个静态的嵌套的接口在我们的码基地。
class Foo {
public static interface Bar {
/* snip */
}
/* snip */
}
我从来没有见过这之前。原始开发者。因此,我要问这样:
什么语义的背后的一个静态界面?什么会改变,如果我删除了 static
?为什么会有人这么做吗?
解决方案
静态的关键字在上面的例子是多余的(一套口是自动的"静态")并且可以删除与没有影响在语义;我会推荐被删除。这同样适用于"公共"在接口中的方法和"公共的最终"上接口领域的修饰语是多余的,只是添加的杂乱的代码。
无论哪种方式,开发是简单地宣布一个接口,名为Foo。酒吧。没有进一步协会与封闭类,除了代码,无法访问Foo会不能访问Foo。酒吧。(源代码或反射就可以访问Foo。酒吧即使Foo是包-私人!)
它是可接受的风格,创造一种嵌套的接口,这样,如果你期待它可以只用从外流,这样,你做的不是创建一个新的顶级名称。例如:
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
(a嵌套类 Foo.Event
是不是坏沿着与此)。
成员接口是隐含静态的。静修改在你的例子可以拆除而无需改变的语义的代码。也参看the Java语言规范 8.5.1.静态部件的类型声明
内部接口已经是静态的,以便被访问。该界面是不相关的类实例,但与这类本身,所以它将被访问 Foo.Bar
, 是这样的:
public class Baz implements Foo.Bar {
...
}
在大多数方面,这不是同一个静态的内类。
杰西的答案是关闭的,但我认为有一个更好的代码,以表明为什么内部接口可能是有用的。看看下面的代码之前你读。你可以找到为什么内部接口是有用的?答案是这类DoSomethingAlready可以化与 任何 类实现一个和C;不仅仅是具体类动物园。当然,这是可以实现的,即使交流是不是内心,但是想象一下长串联的名字(不仅仅是一个和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;
}
}
通常我看到静态的内部课程。静态的内部类不能引用的含有类wherease非静态的课程。除非你是遇到了一些包装冲突(已经有一个接口,称为条中相同的包Foo)我想我会使它它自己的文件。它也可以是一个设计决定的执行之间的逻辑连接Foo和酒吧。也许是作者旨在酒吧只能使用与Foo(虽然一个静态的内部接口不会强制执行此,只是一个合乎逻辑的连接)
如果你会改变class Foo入口Foo"公共"关键字在上面的例子将还有冗余,以及因为
接口内定义的另一个界面 隐含的公共 静态的。
1998年,菲利普浦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.因此,所有其他的答案是正确的:没有差到静止和非静态的嵌套的接口。
在爪哇,静态界面/类允许的界面/类可使用的顶级,也就是说,它可以被宣布为由其他类。所以,你可以这样做:
class Bob
{
void FuncA ()
{
Foo.Bar foobar;
}
}
没有静态的,以上就会失败编译。优点是,你不需要一个新的源文件只是为声明的接口。它还可视同伙的接口条class Foo因为你必须写Foo。酒吧和意味着Foo类的东西的实例Foo。酒吧。
静态意味着任何类一揽子计划的一部分的项目(项目)可以存取权限,它不使用一个指针。这可能是有用的,或阻碍根据不同的情况。
完美的例子usefullnes的"静态"的方法是在数学课。所有的方法,在数学是静态的。这意味着你不需要走出自己的方式,使一个新的实例,宣布变量,并将它们储存在甚至更多的变量,你就可以进入你的数据和得到的结果。
静态并不总是有用的。如果你正在做的情况比较例如,你可能需要存储数据的几个不同的方式。你不能建立三个静态的方法相同的签名。你需要3个不同的情况下,非静态的,然后你就可以和比较,因为如果它是静态的,数据不会改变沿用的输入。
静态的方法是良好的一次回返和快速的计算或很容易获得的数据。