将Java内部类嵌套到一层以上是否合理?

将Java内部类嵌套到一层以上是否合理?,java,inner-classes,Java,Inner Classes,Kushal Paudyal用爪哇语问道。大家一致认为,虽然语言本身没有限制,但底层操作系统和文件系统可能会受到限制 您是否发现过两个或两个以上级别的嵌套内部类有帮助的情况 更新(11/28):如果考虑EnUM类,第二级嵌套是有意义的。在最近的一些重构过程中,我简单地使用了一个外部类(HTTP客户端)、一个内部类(内存缓存)和一个内部类(用于缓存逐出策略)的枚举类。这似乎没什么问题,但就@Thorbjørn而言,我继续从HTTP客户机类中提取缓存类及其内部枚举。我个人没有遇到过需要不止一个的情况

Kushal Paudyal用爪哇语问道。大家一致认为,虽然语言本身没有限制,但底层操作系统和文件系统可能会受到限制

您是否发现过两个或两个以上级别的嵌套内部类有帮助的情况


更新(11/28):如果考虑EnUM类,第二级嵌套是有意义的。在最近的一些重构过程中,我简单地使用了一个外部类(HTTP客户端)、一个内部类(内存缓存)和一个内部类(用于缓存逐出策略)的枚举类。这似乎没什么问题,但就@Thorbjørn而言,我继续从HTTP客户机类中提取缓存类及其内部枚举。

我个人没有遇到过需要不止一个的情况。我可以预见两个可能有用的案例。然而,我很难想象两个以上

我正在想象的例子是JavaGUI代码。在某些情况下,将类嵌套在已经嵌套的ActionListener中可能很有用。

不,我没有

类中类的标准示例是Builder,在Builder中,您有一个子类来帮助创建一个适当的实例,给出了许多可能的配置方法


我个人认为嵌套类的一个更复杂的例子是需要重构的代码的一个很好的例子。

当然-这是有时是有效的。我几分钟前刚做了一些

例如,在我编写的一些测试代码中,我想建立一些处理运行多个可调用项的样板文件。样板需要创建可调用代码块的多个实例。在本例中,我创建了一个工厂实例以传递到threadedTest,该工厂创建了新的可调用项

@Test public void testXXXXXXXX() throws Throwable {
    threadedTest(new CallableFactory() {
        @Override public Callable<Request> create() {
            return new Callable<Request>() {
                // might have state
                @Override public Request call() throws Exception {
                    // do the steps for this test
                    return ...;
                }};
        }});
}
@Test public void testXXXXXXXX()抛出可丢弃的{
threadedTest(新CallableFactory(){
@重写公共可调用的create(){
返回新的可调用(){
//可能有状态
@重写公共请求调用()引发异常{
//执行此测试的步骤
返回。。。;
}};
}});
}
比创建两个新类(其中一个只创建另一个)要简洁得多。当然,在你习惯这种风格之前,这里会有一个可读性的损失,不过


如果将其与模板方法相结合以控制事务或数据库连接/关闭,则可能会导致三个深度。(我有一些类似的代码;如果你这样做了,请确保在注释中编写一个虚拟示例,并很好地解释其结构)

如果你是从一些数据生成代码,嵌套类可以是避免名称冲突的一个好方法。

我看到了嵌套类的许多级别的用法

有一个名为Tandem(HP的)的遗留机器,最初运行COBOL/C代码。后来有一些“补丁”使该机器也能够运行java。COBOL的变量结构自然是多级的(即使是5级也是常见的情况),因此为了允许java调用COBOL服务器,java类也是多级的,以简化它们之间的数据转换


我同意这是一种非常罕见的情况,但无论如何…

我知道我在回收旧线程,但它对我来说是新的:)

我们对POJO使用多个级别来反序列化JSON(使用Jackson)。下面是我们可能从RESTful web服务中获得的JSON的一个小示例(由JSON组成):

{ success: true, response: {
    sales: { item: "123", sales: 3, returns: 1 }, 
    inventory: { item: "567", qty: 100 } 
  }
}
我们过去的POJO设置如下:

public class Json1 {
  private boolean success;
  private JsonResponse response;
}
public class Json1Response {
  private JsonResponseSales sales;
  private JsonResponseInventory inventory;
}
public class Json1ResponseSales {
  private String item;
  private int sales;
  private int returned;
}
public class Json1ResponseInventory {
  private String item;
  private int qty;
}
我们有很多这样的服务,每个web服务请求都有一个POJO。这种布局给了我们一些微不足道的疑问:

  • 请注意,这个相对简单的示例为我们提供了四个类文件。现在将其乘以100,然后再乘以“难度系数”3,以说明大多数JSON比这更混乱的事实。成千上万的文件

  • 字段名在各地重复使用,相同的字段名可能有不同的内容,这取决于哪个web服务。(假设数量可能从一个web服务返回字符串,从另一个web服务返回int,然后乘以100。)

  • 因为这些东西是在父/子关系中绑定在一起的,所以我们决定采用这种布局

    public class Json1 {
      private boolean success;
      private JsonResponse response;
    
      public class Json1Response {
        private JsonResponseSales sales;
        private JsonResponseInventory inventory;
    
        public class Json1ResponseSales {
          private String item;
          private int sales;
          private int returned;
        }
    
        public class Json1ResponseInventory {
          private String item;
          private int qty;
        }
      }
    }
    

    在本例中,我嵌套了两层,但可能更深。可能有四个深

    这些是匿名的内部类,而不是嵌套的内部类。这两个概念在上面被区别对待,很可能是嵌套类,尽管我不想这样写;)他们可以,但他们不是。请注意,我不考虑匿名类。如果您需要“轻松”访问外部变量,它们是一个必要的麻烦。然而,我会强烈地认为另一个匿名类是一个代码气味。