Java 什么';拥有接口/类的公共静态内部类的优点是什么?

Java 什么';拥有接口/类的公共静态内部类的优点是什么?,java,Java,在浏览我的项目的第三方库的一些源代码时,我注意到以下代码模式: public interface MyInterface { public static class MyClass1 implements MyInterface { ... } public static class MyClass2 implements MyInterface { ... } public static class MyClass3 implements MyInterface { .

在浏览我的项目的第三方库的一些源代码时,我注意到以下代码模式:

public interface MyInterface {
    public static class MyClass1 implements MyInterface { ... }
    public static class MyClass2 implements MyInterface { ... }
    public static class MyClass3 implements MyInterface { ... }
}
或者这个:

public class MyBaseClass {
    public static class MyClass1 extends MyBaseClass { ... }
    public static class MyClass2 extends MyBaseClass { ... }
    public static class MyClass3 extends MyBaseClass { ... }
}
现实生活中的例子:

  • SwingX:
    org.jdesktop.SwingX.decorator.HighlightPredicate
    ()
  • Substance:
    org.pushingpixels.Substance.api.renderers.SubstanceDefaultTableCellRenderer
    ()
这样的代码结构有什么好处


我的第一个想法是“聚合”,但使用普通的旧包也可以实现同样的效果。那么什么时候/为什么使用公共内部类而不是包更好呢?

我认为这是由聚合引起的,也许它们也不值得创建顶级类。我有时会这样做,如果有些东西太小,无法创建一个包(将它们与其他包分开),但是相应的类应该只在顶级类的上下文中使用。在我看来,这是一个设计决策

decorator模式可能是一个很好的例子,它们可以应用于顶级类,但可能太简单了,不值得也应用于顶级类。通过将它们用作内部类,可以轻松地显示所有权

乍一看,这在软件包中并不明显。您可以直接看到依赖类/接口


此外,还可以访问类的私有字段,这可能很有用,并且比包私有范围更细粒度

我能想到的一个用途是提供接口的现成实现,任何人都可以公开使用,但在概念上仍然绑定到母接口


只有当接口很简单(因此内部实现类很小),没有太多,并且大多数接口客户机实际上需要它们时,这才有意义。否则,它们会使源文件变得混乱,使其更难理解。

内部接口必须是静态的才能被访问。接口不与类的实例相关联,而是与类本身相关联,因此可以使用
Foo.Bar
,就像这样。

就类及其内部类而言(不适用于接口)。一个区别是内部类可能使用外部类的私有成员,如果他们是“兄弟”(独立的顶级类),情况就不是这样了

例如:

public class MyBaseClass {

    private static String staticField = "outer";

    public static class MyClass1 extends MyBaseClass { 

      public MyClass1() {
          MyBaseClass.staticField = "inner1";
      }

    }
}

如果您将
MyClass
移出外部类,这将不起作用。

我认为公共静态内部类的原因是“基本”类的附加工具或实用程序。

多年前,当我问我的老师这方面的问题时,他回答说,通过这种方式,您可以为同一对象公开一个完全不同的接口。假设你有

public class MyBaseClass {
    public static class MyClass1 {
       public int myClassMethod1() {...}
       public int myClassMethod2() {...}
    }
    ...
    public void myBaseMethod1() {...}
    public void myBaseMethod2() {...}
}
由于
MyClass1
的实例可以访问
MyBaseClass
的内部,因此您可以根据需要公开与
MyClass1
实例或
MyBaseClass
实例相同的内部行为,即使两个类中定义的方法完全不同


我从来都不需要使用它,但它真的很有趣。

这样做可以为您节省一些额外的源代码文件,并可以为类提供一个很好的层次名称,即
org.foo.bar.XY.Default
而不是
org.foo.bar.DefaultXY

我没有查看您发布的实际示例,但是一个区别是,内部类可能使用外部类的私有成员,如果它们是“兄弟”(独立的顶级类),则情况并非如此。顺便说一句:内部类对于接口默认是静态的,您不能为接口使用非静态嵌套类。@Peter:但是关键字
static
是可选的。对于一个接口来说,所有内部类都是静态的。@John,没错,
public
也一样当children类本身没有意义时,可以这样建模父子关系。例如Map.Entry;如果条目本身与某种地图无关,则不会有条目,因此它们不应该是顶级类。