Java内部类扩展了外部类

时间:2011-08-19 17:26:50

标签: java inner-classes extends outer-classes

在Java中有一些内部类扩展外部类的情况。

例如,java.awt.geom.Arc2D.Float是java.awt.geom.Arc2D的内部类, 并且还扩展了Arc2D。 (c.f。http://download.oracle.com/javase/6/docs/api/java/awt/geom/Arc2D.Float.html

此外,sun.org.mozilla.javascript.internal.FunctionNode.Jump扩展了sun.org.mozilla.javascript.internal.Node,它是FunctionNode的超类。 (抱歉......找不到javadoc的链接)

对我来说,这似乎很奇怪。你能创建这些吗?

new Arc2D.Float.Float() //n.b. I couldn't get this to compile in Intellij IDEA;

new FunctionNode.Jump.Jump.Jump(1); // I could get this to compile

将子类嵌套为超类的内部类有什么作用?

我想知道是否要访问超类中的某些内容,但是如果你想访问父类中的任何变量/方法,你可以使用

super.variable;

super.method();

编辑1: jjnguy建议将逻辑保持在同一个地方。在这种情况下,为什么不写一个文件com.mypackage.AbstractTest:

abstract class AbstractTest {
  abstract String getString();
}

class ExtensionTest extends AbstractTest {
  @Override
  String getString() {
    return "hello world";
  }
}

......而不是:

abstract class AbstractTest {
  abstract String getString();

  class ExtensionTest extends AbstractTest {
    @Override
    String getString() {
      return "hello world";
    }
  }
}

编辑2: 正确地指出,我之前编辑中的建议存在缺陷,因为无法在包外构建ExtensionTest。但是,周末我对此有了进一步的考虑,那么下面会怎么样:

abstract class Test {
  public class ExtensionTest extends AbstractTest {
    @Override
    String getString() {
      return "hello world";
    }
  }

  private abstract class AbstractTest {
    abstract String getString();
  }
} 

从本质上讲,到目前为止我看到的最好的答案是内部类扩展其外部类允许将逻辑组合在一起。但是,我认为这可以在没有扩展名的情况下完成。

在我看来,拥有一个可以在其中嵌套无数个相同子类的类似乎是糟糕的设计。 (上下文:在尝试为代码完成实用程序生成字典时出现了这个问题,并抛出了一个StackOverflowException。我找到了一个解决方法,但我无法理解为什么它是这样设计的。)

3 个答案:

答案 0 :(得分:12)

看看Java的Point2D。它有两个内部类,它们是它的子类。

重要的是要注意它们是static内部类。这与普通的内部阶级完全不同。就像静态方法一样,静态类是在类级而不是对象级定义的。

Point2D的情况下,完成逻辑耦合类及其逻辑。它可以帮助abstract类型Point2D的用户找到他们可以使用的实现。

为了回应你的编辑,我想指出一个重要的事实。单个Java文件可能只包含一个公共类,除了用于公共内部类。虽然您的两个示例都可以编译,但它们不允许向公众访问这些类。如果要在单个文件中向某人提供多个公共类,则必须使用公共静态内部类。

答案 1 :(得分:7)

有两种内部类:

  • 静态内部类。内部类继续引用外部类。

  • 非静态内部类。内部类确实保留对外部类的引用。

扩展外部类的静态内部类的情况不像扩展外部类的非静态内部类那样有趣。

后者会发生什么:创建内部类,需要引用外部类。但是,由于内部类是外部类的实例,因此它还接受对内部类的另一个实例的引用,以用作外部类。

让我们看看一些代码:

Outer a = new Outer();
Outer.Inner b = a.new Inner();

// Only possible when Inner extends Outer:
Outer.Inner c = a.new Inner().new Inner();

如果你知道构建器模式,可以使用它来获得它的OOP版本:

public abstract class Command {

    // Not possible to create the command, else than from this file!
    private Command() {
    }

    public abstract void perform();

    public static class StartComputer extends Command {
        public void perform() {
            System.out.println("Starting Computer");
        }
    }

    public class OpenNotepad extends Command {
        public void perform() {
            Command.this.perform();
            System.out.println("Opening Notepad");
        }
    }

    public class ShutdownComputer extends Command {
        public void perform() {
            Command.this.perform();
            System.out.println("Shutting Computer");
        }
    }

}

用作:new Command.StartComputer().new OpenNotepad().new ShutdownComputer().perform();

答案 2 :(得分:2)

第一个在我的IntelliJ上编译好。

严格地说,静态成员类不是内部类。它们被称为嵌套类。