我有一个大约 4,000 行长的 Java 类(有很多方法)。然后这个类使用了大约 200 个它需要的小类,所以又需要 4,000 行代码。
如果这是 C#,我会将其他内容放入部分类文件(不同的文件)中,但它们将保留私有嵌套类,仅对父类可见。
有没有办法在Java中做到这一点?我并不是要求某些方法位于不同的文件中,而是要求私有嵌套类位于不同的文件中。
您不能将一个类仅对另一个类私有,同时将其放入不同的文件中。
您可以做的是将这些类放在没有访问修饰符的单独文件中(省略“public”),这将使它们成为包私有的,即仅在其自己的包中可见。另请参阅官方访问控制教程。
UtilClasses.java:
package OurPackage;
class UtilClass1
{
}
class UtilClass2
{
}
MainClass.java:
package OurPackage;
public class MainClass
{
UtilClass1 iAmAUtilClass;
}
您还可以通过省略嵌套类中的访问修饰符,使用接口或继承来实现类似的效果。这也将是包私有的,但在某些情况下这可能比上面的更好,因为它避免了所有嵌套类都位于顶层。
BaseInterface.java:
package OurPackage;
interface BaseInterface
{
class UtilClass1
{
}
}
MainClass.java:
package OurPackage;
public class MainClass implements BaseInterface
{
UtilClass1 iAmAUtilClass;
}
您还可以使用基类代替接口并扩展它,效果大致相同。
您不需要实现
BaseInterface
即可访问其嵌套类,但是,如果您不这样做,则需要使用 BaseClass.UtilClass1
而不仅仅是 UtilClass1
。
内部私有类无法“提取”,并且仍然仅对一个特定类可见。评论中已经提到了一种解决方案:创建一个包含“主”类和所有先前内部类的包,并使内部类包可见。这还允许您创建单元测试来测试内部类的正确功能,这目前很可能不会发生,因为单元测试目前无法“到达”内部类。
Java 中不存在像 C++ 中那样在类之间声明“友谊”的概念。
您可以用顶级内部类替换内部类,但是您必须手动重写编译器自动为您连接内部类关系的许多内容。对于虚拟机来说,内部类没有什么特别的,它只是与外部类位于同一包中的另一个类,具有一个奇特的名称。但是编译器在底层创建了很多帮助器构造,您必须手动重建它们(或者使用一些重构工具为您做这件事):
this
实例。您需要将外部 this
传递到内部构造函数中,并将其存储在像 outerThis
这样的字段中才能访问。outerThis.method()
一样重写它。这同样适用于字段。最终,您将拥有以前的内部类,至少是包可见的,并且比原始内部类更详细,但另一方面,您将获得更好的隔离性和可测试性。
这里有一种使用 JUnit 5 来实现这一点的方法(在 Kotlin 中,但稍作修改也应该适用于 Java)。
MyContainerTest.kt(或.java)文件:
class MyContainerTest {
@Nested inner class MyNestedTestsOne : MyNestedTest1()
@Nested inner class MyNestedTestsTwo : MyNestedTest2()
// Can also have regular unit tests
@Test
fun myUnitTestInContainer() { /* ... */ }
@Test
fun myOtherUnitTestInContainer() { /* ... */ }
}
MyNestedTest1.kt(或.java)文件:
abstract class MyNestedTest1 {
@Test
fun myUnitTestInNestedClass1() { /* ... */ }
}
MyNestedTest2.kt(或.java)文件:
abstract class MyNestedTest2 {
@Test
fun myUnitTestInNestedClass2() { /* ... */ }
}
嵌套测试类已被提取到单独的文件中,然后在所需的容器类中,已创建从这些类继承的占位符嵌套类。这样,它们在测试视图和报告中显示为容器测试类的子层次结构。
注意:使这些嵌套类抽象以避免运行它们两次。