为什么 Java API 中的许多方法都有 "abstract" 修饰符?

Why do many of the methods in the Java API have "abstract" modifiers?

学生级别的问题,希望Whosebug能帮我加深理解:

我注意到 Java API 中的许多方法(例如 Graphics2D 中的方法)都有 "abstract" 修饰符。这是为什么?

我现在只是在研究继承和多态性,但据我了解,抽象 class 旨在用作一种 "parent class" 扩展sub-classes,并且抽象 classes 本身无法实例化。

我也明白抽象方法是在抽象 class 中声明的(但未实现),并且据说必须在子 class 中实现才能使子 class被认为是非抽象的(因此是可实例化的)。

那么,我是如何导入一个像 Graphics2D 这样的 class,创建它的一个实例并使用它的抽象方法的呢?

我的导师提到了一些关于方法在 运行 时间被覆盖的事情(?),但我不明白 how/why。显然我在这里遗漏了一些东西,我希望有更多的见解!

So, how is it that I'm able to import a class like Graphics2D, create an instance of it and use its abstract methods?

因为您从未直接创建Graphics2D的实例。看看你的代码 - 你不会找到这个:

Graphics2D graphics = new Graphics2D(); // This wouldn't compile

...任何地方。相反,您会发现对 returnGraphics2D 的方法的调用实际上是 return 对具体子 [=33] 实例的引用=]是的。或者,也许您将提供接受调用者提供的 GraphicsGraphics2D 参数的方法...并且调用者 可能 知道具体的 class,或者他们也可能从其他地方获得了参考资料。

在某些方面,这就是重点 - 您甚至想知道这些子 class 在哪里这一事实证明了整个事情的运作情况......您只需要处理 Graphics2D,但其实现细节可能因平台等而异。

当您的讲师谈论被覆盖的方法时,我怀疑他们实际上说的是 覆盖 - 其中 subclass 可以提供比方法更具体的实现一个 superclass,或者确实可以提供一个 superclass 只有抽象方法声明的地方。

这是为了将实现与定义分开;类似于 C/C++ 头文件。

让我们想一想我们在 Java 中都使用的一些基本 class 元素,例如 InputStream。我们知道我们需要一种阅读方式,因此我们定义了几个适当的抽象方法,但还没有实际实现。

这对我们是有利的,因为如果一个class继承自InputStream,我们知道它会实现我们最初定义的读取方法。通常这些实现不同于 sublcass 到 subclass.

例如,让我们考虑 InputStream 的几个子 classess,例如 GZIPInputStreamFileInputStreamGZIPInputStream 将不得不在其读取调用中解压缩字节。 FileInputStream 只需从其构造函数中传递的文件中读取字节。你可以看到这是怎么回事。