嵌套Java内部类超过一层深度是否合理?

10
Kushal Paudyal问Java中内部类可以嵌套多深。共识是,虽然语言本身没有限制,但底层操作系统和文件系统可能会有限制。
您是否曾经发现两个或更多级别的嵌套内部类有所帮助?
更新(11/28):如果考虑枚举类,则第二层嵌套可能是有意义的。在最近的一些重构过程中,我简要地拥有了一个外部类(HTTP客户端),一个内部类(内存缓存),以及在内部类中的枚举类(用于缓存逐出策略)。这似乎还不错,但根据@Thorbjørn的观点,我继续提取缓存类及其内部枚举类,将它们从HTTP客户端类中提取出来。
6个回答

5

没有。

一个类内部的标准示例是Builder,其中你有一个子类来帮助创建一个正确的实例,给定了许多可能的配置方法。

个人认为,更复杂的嵌套类是需要重构的优秀示例。


请注意,我在此不考虑匿名类。如果您需要“轻松”访问外部变量,则它们是必要的麻烦。然而,我强烈认为在另一个匿名类内部使用匿名类是一种代码异味。 - Thorbjørn Ravn Andersen

4

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


3

我个人没有遇到过需要超过一个的情况。我可以想象两个可能会有用。然而,我很难想象超过两个的情况。

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


3

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

我们使用多个级别的POJO来反序列化JSON(使用Jackson)。这里是一个我们可能从RESTful web服务返回的JSON的微小示例(虚构):

{ success: true, response: {
    sales: { item: "123", sales: 3, returns: 1 }, 
    inventory: { item: "567", qty: 100 } 
  }
}

我们过去的POJOs设置如下:

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。这种布局给我们带来了一些微小的疑虑:
  1. 请注意,这个相对简单的例子给我们带来了四个类文件。现在将其乘以数百个,再乘以一个难度系数3,以应对大多数JSON比这要麻烦得多的事实。成千上万的文件。

  2. 字段名称在各个地方被重复使用,并且同一个字段名称可能根据Web服务的不同而具有不同的内容。(想象一下数量可能从一个Web服务返回为字符串,从另一个Web服务返回为整数,然后将其乘以数百个。)

由于这些东西在父/子关系中绑定在一起,因此我们决定采用这种布局。
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;
    }
  }
}

在这种情况下,我嵌套了两层,但可能更多。也许高达四层深度。

2

我看到了嵌套类的层数使用情况。

有一台名为Tandem(来自HP)的遗留机器,最初运行COBOL/C代码。后来有“补丁”使该机器能够运行Java。COBOL的变量结构通常是多层的(甚至5层也很常见),因此为了让Java能够调用COBOL服务器,Java类也是多层的,以简化它们之间数据的转换。

我同意这是一个非常不寻常的情况,但无论如何...


1

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

例如,在我编写的某些测试代码中,我想设置一些样板文件来处理运行多个可调用项。这个样板需要创建多个可调用代码块的实例。在这个例子中,我正在创建一个工厂的实例以传递到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 ...;
                }};
        }});
}

比创建两个新类更简洁,其中一个只是创建另一个。当然,在你习惯这种风格之前,这里会有可读性的惩罚...

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


1
这些是匿名内部类,而不是嵌套内部类。这两个概念在http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html中被不同地处理。 - Thorbjørn Ravn Andersen
1
以上内容本来可以使用嵌套类实现,但我不想那样写 ;) - Scott Stanchfield
2
他们本来可以,但他们没有。 - Thorbjørn Ravn Andersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接