内部类是否常用于Java? 他们“坏”吗?

内部类是否常用于Java? 这些是否与嵌套类相同? 或者用Java更换这些更好的东西? 我有一本关于第5版的书,它有一个使用内部类的例子,但我想我读过一些内部类是“坏”的。

我不知道,并希望有关于它的想法。

谢谢。

经常使用内部类,并且非常相似的东西 – 匿名类 – 实际上是不可或缺的,因为它们是Java最接近闭包的东西。 所以,如果你不记得你在哪里听到内心阶级是坏的,试着忘掉它!

他们并非“坏”。

它们可能会受到滥用(例如内部类的内部类)。 一旦我的内部类跨越了几行,我宁愿将它提取到自己的类中。 它有助于提高可读性,并在某些情况下进行测试。

有一个问题不是很明显,值得记住。 任何非static内部类都将具有对周围外部类的隐式引用(隐式“this”引用)。 这通常不是问题,但是如果你来序列化内部类(比方说,使用XStream ),你会发现这会导致你意想不到的悲伤。

我认为他们不是邪恶的。 也许它们没有被广泛使用,但它们确实有很多用途,回调就是其中之一。 一个特殊的优点是它们可以从与外部类不同的类扩展,因此您可以拥有多个inheritance。

我会说内部类的一个问题是它们的语法有点“难看”。 这是让一些人望而却步的东西。 在这里工作的有很多。

内部类的一个很好的例子是给定集合类型的迭代器实现。 它是一个实现公共接口的类,但除了与另一个类关联外没有任何业务存在。 它允许您使用友元操作符对C ++中您将被强制执行的操作进行建模。

非静态内部类可以隐藏性能问题。 他们可以访问封闭类的成员字段,但不能直接访问,而是通过自动创建的getter访问。 这比将封闭类的成员复制到内部类要慢。

这里描述了非静态内部类的一些其他问题

它们很有用,可以非常常用。 虽然您应该对滥用function持谨慎态度,但它们不会比任何其他语言function更容易被滥用。

要记住的关键是你要通过使两个类更加紧密耦合来交换灵活性以简化和凝聚。 您可能希望这些类紧密绑定,但是您放弃了通过不从包含类之外的接口定义类来透明地将其他类交换到当前嵌入类的位置的能力。

请考虑以下示例:

 public class OuterClass { private AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass() { @Override protected void printAboutme() { System.out.println("AnonymousInnerClass.printAboutMe........."); Class clazz = this.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected"); message = message + " " + field.getType().getSimpleName(); message = message + " " + field.getName(); System.out.println(message); } } }; public void displayAnonymousInnerClass() { anonymousInnerClass.printAboutme(); } public void displayStaticInnerClass() { NestedStaticClass staticInnerClass = new NestedStaticClass(); staticInnerClass.printAboutMe(); } public void displayInnerClass() { InnerClass innerClass = new InnerClass(); innerClass.printAboutMe(); } public void displayMethodInnerClass(){ class MethodInnerClass { private String sampleField = "Method Inner Class"; public void printAboutMe() { System.out.println("MethodInnerClass.printAboutMe........."); Class clazz = this.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected"); message = message + " " + field.getType().getSimpleName(); message = message + " " + field.getName(); System.out.println(message); } } } MethodInnerClass methodInnerClass = new MethodInnerClass(); methodInnerClass.printAboutMe(); } class InnerClass { private String sampleField = "Inner Class"; public void printAboutMe() { System.out.println("InnerClass.printAboutMe........."); Class clazz = this.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected"); message = message + " " + field.getType().getSimpleName(); message = message + " " + field.getName(); System.out.println(message); } } } abstract class AnonymousInnerClass { protected String sampleField = "Anonymous Inner Class"; protected abstract void printAboutme(); } static class NestedStaticClass { private String sampleField = "NestedStaticClass"; public void printAboutMe() { System.out.println("NestedStaticClass.printAboutMe........."); Class clazz = this.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected"); message = message + " " + field.getType().getSimpleName(); message = message + " " + field.getName(); System.out.println(message); } } } 

}

在这个例子中,每种类型的非静态嵌套类与静态嵌套类进行比较。现在,如果你为每个嵌套类运行外部类的显示方法,你将看到每个嵌套类printAboutMe()方法的输出,它有一些reflection代码打印嵌套类的所有成员变量。

您将看到非嵌套类在代码中除了声明的变量字符串之外还有一个额外的成员变量,它仅在运行时出现。

例如,如果我们为InnerClass执行以下代码。 : –

 public class NestedClassesDemo { public static void main(String[] args) { OuterClass outerClass = new OuterClass(); outerClass.displayInnerClass(); } 

}

输出是这样的: –

 InnerClass.printAboutMe......... private String sampleField protected OuterClass this$0 

注意有一个神秘的成员变量这个$ 0类型封闭类(外类)。

现在你清楚内部类继续引用外部类。所以你将内部类的引用传递给其他外部世界类的图像场景然后引用永远不会被释放到OuterClass也被引用,因此泄漏。

因此,如果不使用内部类,这会使内部类变坏。

静态内部类没有这种情况。请运行所有显示方法。如果代码中有任何问题请指出。