Java内部类扩展外部类

Java内部类扩展外部类,java,inner-classes,extends,outer-classes,Java,Inner Classes,Extends,Outer Classes,在Java中,有些情况下内部类扩展外部类 例如,java.awt.geom.Arc2D.Float是java.awt.geom.Arc2D的内部类, 并且还扩展了Arc2D。 (c.f.) 此外,sun.org.mozilla.javascript.internal.FunctionNode.Jump扩展了sun.org.mozilla.javascript.internal.Node,它是FunctionNode的一个超类。 (抱歉…找不到指向javadoc的链接) 对我来说,这似乎很奇怪。然

在Java中,有些情况下内部类扩展外部类

例如,java.awt.geom.Arc2D.Float是java.awt.geom.Arc2D的内部类, 并且还扩展了Arc2D。 (c.f.)

此外,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;

编辑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。我找到了一个解决方法,但我无法理解为什么它是这样设计的。)

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

需要注意的重要一点是,它们是
静态的
内部类。这是一个完全不同的意思,一个规则的内部类。与静态方法一样,静态类是在类级别而不是对象级别定义的

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


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

内部类有两种情况:

  • 静态内部类。内部类不保留对外部类的引用

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

扩展外部类的静态内部类不如扩展外部类的非静态内部类有趣

后一种情况是:要创建内部类,需要引用外部类。但是,由于内部类是外部类的实例,因此它还接受对内部类的另一个实例的引用,以用作外部类

让我们看一些代码:

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命令。StartComputer().new OpenNotepad().new ShutdownComputer().perform()

在我的IntelliJ上,第一个编译得很好


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

@jinguy给出了一个很好的答案来解释为什么。对于您的示例,
javac
将愉快地编译行
objectobj3=newjava.awt.geom.Arc2D.Float.Float()。我可以理解你的推理,但我认为有更好的方法。。。请参阅我对问题的编辑。@amaid,请参阅我添加的最后一段。如果您想呈现多个公共类。。。在一个文件中,这正是我有时做这种事情的原因。顺便说一句,有人可能是我自己——只是为了我自己的方便而将类“打包”在一个文件中。@a介质当前您的内部类不是声明为静态的(注意
Arc2D.Float
是静态的)。对我来说,这是一个不同的世界,基本上破坏了我所能想象到的每一个好处。如果您要讨论未声明为
静态的
命名内部类,那么我唯一的建议就是像瘟疫一样避免它。在我的书中,静态命名的内部类是可以的,非静态类只不过是总数disaster@amaid,“为什么您希望内部类扩展其外部类”-您不会。这就是我在其他评论中想要表达的。你认为这个例子很好吗?看起来很糟糕,我同意!它看起来很糟糕,需要一些时间来适应。我以前从未见过它被使用过。这在一些地方很普遍吗?哇,这看起来很奇怪,但我喜欢。您还可以使用decorator模式,使代码看起来像new Command.StartComputer(new Command.OpenNotepad(new Command.ShutdownComputer()).perform()。但是你的代码必须从StartComputer开始。您是如何找到这个解决方案的?或者只是做一些普通的事情,让您的方法返回它们所处的类型,这样您就可以在不使用new关键字的情况下获得语法,而实例化较少的静态嵌套类更为准确。根据定义,声明为静态的嵌套类称为静态嵌套类。非静态嵌套类称为内部类。
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");
        }
    }

}