在Java中使用大型内部类是不是很糟糕?

时间:2010-09-21 22:42:44

标签: java inner-classes

我有很多ContainedClass类型的对象存储在ContainingClass类型的对象中。我需要从内部对象访问容器对象。截至目前,我通过在ContainedClass cclass = new ContainedClass(this);等其他对象的构造函数中传递对容器对象的引用并将其存储为ContainingClass owner来实现此目的。

这对我来说似乎很难看,而且似乎适合我的解决方案是使用内部类,但ContainedClass的定义非常大,这似乎是不合适的。那么我应该选择哪个选项?还是我还缺少另一个明显的选择?

这是我在网上找到的一段示例代码,描述了我使用内部类的目的。

public class TestIt {
  public static void main(String a[]){
     new TestIt().doit();
     /*
      output :
      Hello world!
     */ 
  }
  public void doit() {
      new InnerClass().sayHello();
  }
  public void enclosingClassMethod(){
      System.out.println("Hello world!");
  }


 class InnerClass {
   public void sayHello() {
     TestIt.this.enclosingClassMethod();
   }
 }
}

我应该补充一点,我所看到的内部类的另一个好处是ContainedClass只能存在于ContainerClass中,这是一个理想的结果。

6 个答案:

答案 0 :(得分:3)

您对ContainedClass cclass = new ContainedClass(this);构造所做的事情正在复制内部类所做的内容。可能有理由不使用内部类,但类的大小实际上并不是其中之一。我会使用真正的语言功能,而不是模仿它,除非有充分的理由不使用真正的交易。

答案 1 :(得分:2)

我认为这取决于父/子课程的高度耦合程度。如果孩子需要访问许多你不会通过getter / setter或者许多其他方式私有的成员函数公开的成员变量,那么内部类安排将更加清晰。

但是如果子类将使用父级的现有公共接口,那么我认为将它们分开是更清晰的。仅向构造函数添加一个附加参数也不错。您甚至可以引入一个界面来描述从子项访问父项的哪些部分。这样可以很容易地将子类与父类分开进行单元测试(例如,使用模拟对象)。

答案 2 :(得分:1)

在这种情况下我会使用factoryMethod:

class ContainingClass {
...
    ContainedClass createContainedObject() {
        return new ContainedClass(this);
    }
...
}

在代码中看起来像

jar = new ContainingClass();
bean = jar.createContainingClass();

这有点踩到了这个问题,但我发现它具有表现力并允许我选择是否使用内部类。我个人不喜欢大型的内部课程,我觉得它们很难阅读。

答案 3 :(得分:0)

如果我是你,我会坚持你以前做的事情,而不是转向内部阶级。它们的语法有时是不合适的(特别是因为它不是静态内部类,而是每个实例类),而你只是在一个文件中填充大量代码。

您之前使用的父/子关系并不是那么罕见,而且我个人并不觉得这样丑陋。

答案 4 :(得分:0)

任何风味的大类都应该不受欢迎,因为它们往往有多重责任,并且很难分离和测试。

您的解决方案最终将取决于ContainedClass需要了解ContainerClass的原因。如果目的是在ContainedClasses之间共享公共数据/初始化代码,那么Factory方法可能会产生良好的结果。或者,如果您只是想跟踪ContainedClasses,那么您可能需要考虑一个Event / EventListener模型。

答案 5 :(得分:0)

  1. 内部类应该用于创建一次性对象。
  2. 如果只有顶级类使用此类,则转到内部类。
  3. 请阅读Joshua Bloch撰写的Effective Java,以获得清晰的想法。