Kushal Paudyal 询问在 Java 中可以嵌套多深的内部类。共识是,虽然语言本身没有限制,但底层操作系统和文件系统可以。
你有没有发现两层或多层嵌套内部类有用的案例?
更新 (11/28):如果您考虑枚举类,第二层嵌套可能是有意义的。在最近的一些重构中,我简要地有一个外部类(一个 HTTP 客户端)、一个内部类(一个内存缓存)和一个内部类内部的枚举类(用于缓存驱逐策略)。这似乎没问题,但就@Thorbjørn 而言,我继续从 HTTP 客户端类中提取缓存类及其内部枚举。
Kushal Paudyal 询问在 Java 中可以嵌套多深的内部类。共识是,虽然语言本身没有限制,但底层操作系统和文件系统可以。
你有没有发现两层或多层嵌套内部类有用的案例?
更新 (11/28):如果您考虑枚举类,第二层嵌套可能是有意义的。在最近的一些重构中,我简要地有一个外部类(一个 HTTP 客户端)、一个内部类(一个内存缓存)和一个内部类内部的枚举类(用于缓存驱逐策略)。这似乎没问题,但就@Thorbjørn 而言,我继续从 HTTP 客户端类中提取缓存类及其内部枚举。
不我没有。
类中的类的标准示例是 Builder,其中您有一个子类来帮助创建一个适当的实例,给定许多可能的配置方法。
就个人而言,我认为嵌套类的更复杂情况是需要重构的代码的极好示例。
我个人还没有遇到过证明需要不止一个的案例。我可以预见两个可能有用的情况。然而,我很难想象超过两个。
我想象的例子是 Java GUI 代码。在某些情况下,将类嵌套在已经嵌套的 ActionListener 中可能很有用。
如果您从某些数据生成代码,嵌套类可能是避免名称冲突的好方法。
我看到了嵌套类级别数的用法。
有一台名为 Tandem(HP)的遗留机器,它最初运行 COBOL/C 代码。后来的“补丁”也使该机器也可以运行java。COBOL 的变量结构自然是多级的(甚至 5 级也是常见的情况),所以为了让 java 调用 COBOL 服务器,java 类也是多级的,以简化它们之间的数据转换.
我同意这是一个非常罕见的情况,但无论如何......
我知道我正在回收一个旧线程,但这对我来说是新的:)
我们为我们的 POJO 使用多个级别来反序列化 JSON(使用 Jackson)。这是我们可能从 RESTful Web 服务返回的 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 服务返回为字符串,从另一个返回为 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;
}
}
}
在这种情况下,我嵌套了两层,但可能更多。也许高达四深。
当然 - 这有时是有效的。我几分钟前刚做了一些。
例如,在我编写的一些测试代码中,我想设置一些样板来处理运行多个可调用对象。样板文件需要创建可调用代码块的多个实例。在此示例中,我创建了一个工厂实例以传递给 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 ...;
}};
}});
}
比创建两个新类(其中一个只创建另一个类)要简洁得多。当然,在您习惯这种风格之前,这里的可读性会受到影响,不过......
如果你将它与模板方法结合起来来控制事务或数据库连接/关闭,这可能会达到三个深度。(我有一些这样的代码;如果你这样做,请确保你在评论中写了一个虚拟样本并很好地解释了结构)