简体   繁体   English

Java:有没有办法将嵌套类放在一个单独的文件中?

[英]Java: Is there a way to put nested classes in a separate file?

I have a Java class that is about 4,000 lines long (lots of methods). 我有一个大约4,000行的Java类(很多方法)。 This class then uses about 200 small classes that only it needs, so another 4,000 lines of code. 然后这个类使用大约200个只需要它的小类,所以另外有4,000行代码。

If this was C# I would put those other in a partial class file so different file, but they would remain private nested classes only visible to the parent class. 如果这是C#,我会将其他文件放在部分类文件中,但是它们仍然是父类可见的私有嵌套类。

Is there a way to do this in Java? 有没有办法在Java中这样做? I'm not asking for some methods to be in a distinct file, but for private nested classes to be in a distinct file. 我不是要求某些方法位于不同的文件中,而是要将私有嵌套类放在不同的文件中。

thanks - dave 谢谢 - 戴夫

You can't make a class private to only another class while putting it in a different file. 在将类放在不同的文件中时,不能将类专用于另一个类。

Use no class access modifier 不使用类访问修饰符

What you can do is put the classes in separate files with no access modifiers (omit "public"), which will make them package-private, ie visible only within its own package. 你可以做的是把类放在没有访问修饰符的单独文件中(省略“public”),这将使它们成为包私有,即只在它自己的包中可见。 See also the official Access Control tutorial . 另请参阅官方访问控制教程

UtilClasses.java: UtilClasses.java:

package OurPackage;

class UtilClass1
{
}
class UtilClass2
{
}

MainClass.java: MainClass.java:

package OurPackage;

public class MainClass
{
   UtilClass1 iAmAUtilClass;
}

Use interfaces or inheritance 使用接口或继承

You can also achieve something similar with either interfaces or inheritance, by omitting the access modifier from the nested class. 通过省略嵌套类中的访问修饰符,您还可以实现与接口或继承类似的操作。 This would also be package-private, but this might be preferable to the above in some circumstances, since it avoids having all the nested classes at the top level. 这也是包私有的,但在某些情况下这可能比上面更好,因为它避免了所有嵌套类在顶层。

BaseInterface.java: BaseInterface.java:

package OurPackage;

interface BaseInterface
{
   class UtilClass1
   {
   }
}

MainClass.java: MainClass.java:

package OurPackage;

public class MainClass implements BaseInterface
{
   UtilClass1 iAmAUtilClass;
}

You can also use a base class instead of an interface and extend that with roughly the same effect. 您还可以使用基类而不是接口,并以大致相同的效果扩展它。

You don't need to implement BaseInterface gain access to its nested classes, but, if you don't, you'd need to use BaseClass.UtilClass1 instead of just UtilClass1 . 您不需要实现BaseInterface获取对其嵌套类的访问权限,但是,如果不这样做,则需要使用BaseClass.UtilClass1而不仅仅是UtilClass1

Inner private classes can't be "extracted" and still be visible only to one particular class. 内部私有类不能被“提取”,并且仍然只对一个特定类可见。 One solution is already mentioned in the comments: Create a package that contains the "main" class and all the previously inner classes and make the inner classes package visible. 注释中已经提到了一个解决方案:创建一个包含“main”类和所有以前内部类的包,并使内部类包可见。 This would also allow you to create unit tests testing for the correct functionalities of the inner classes, which is something that is most likely currently not happening simply because the inner classes can't be "reached" by a unit test at the moment. 这也可以让你创建单元测试来测试内部类的正确功能,这是目前最不可能发生的事情,因为内部类目前无法通过单元测试“到达”。

Concepts like declaring "friendships" between classes like in C++ don't exist in Java. 在Java中不存在像在C ++中声明类之间的“友谊”这样的概念。

You can replace the inner classes with top-level ones, but you'll have to rewrite a lot of things by hand that the compiler auto-wires for you with the inner-class relationship. 您可以使用顶级类替换内部类,但是您必须手动重写许多内容,编译器会使用内部类关系为您自动连接。 To the Virtual Machine, an inner class is nothing special, it's just another class in the same package as the outer class with a fancy name. 对于虚拟机而言,内部类并不特别,它只是与具有奇特名称的外部类相同的包中的另一个类。 But the compiler creates a lot of helper constructs under the hood, that you have to reconstruct by hand (or have some refactoring tool do that for you): 但是编译器在底层创建了很多辅助构造,你必须手工重建(或者有一些重构工具为你做):

  • The inner class can refer to the outer this instance, by prefixing it with the outer class name. 内部类可以通过在前面加上外部类名称来引用外部的this实例。 You need to pass the outer this into your inner constructor and store it in a field like outerThis to get access. 您需要外通过this到你内心的构造函数,并将其存储在像场outerThis获取访问权限。
  • In the source code, you can call the outer-class methods directly. 在源代码中,您可以直接调用外部类方法。 You need to rewrite it like outerThis.method() . 你需要像outerThis.method()一样重写它。 The same applies to fields. 这同样适用于领域。
  • For private outer methods and fields to become accessible, the compiler creates bridge constructs for you. 要使私有外部方法和字段可访问,编译器将为您创建桥构造。 You have to either change access modifiers or create package-private bridge methods yourself. 您必须自己更改访问修饰符或创建包私有桥方法。

In the end, you'll have the former inner classes at least package-visible and being more verbose than the original ones, but on the other hand you'll get better isolation and testability. 最后,您将使前面的内部类至少包装可见并且比原始类更冗长,但另一方面,您将获得更好的隔离和可测试性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM