Java中的“抽象类”是什么?
当前回答
抽象类是不能被实例化的类。抽象类是通过创建可实例化的继承子类来使用的。抽象类为继承的子类做了一些事情:
定义可由继承子类使用的方法。 定义继承子类必须实现的抽象方法。 提供一个公共接口,允许子类与所有其他子类交换。
这里有一个例子:
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
注意,“abstractMethod()”没有任何方法主体。因此,你不能做以下事情:
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
没有实现abstractMethod()的方法!因此,当JVM获得像new ImplementingClass(). abstractmethod()这样的东西时,它无法知道应该做什么。
这是一个正确的实现类。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
注意,您不必定义implementedMethod()或finalMethod()。它们已经由AbstractClass定义。
这是另一个正确的ImplementingClass。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
在本例中,您重写了implementedMethod()。
但是,由于final关键字,不能执行以下操作。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
public void finalMethod() { System.out.print("ERROR!"); }
}
您不能这样做,因为AbstractClass中finalMethod()的实现被标记为finalMethod()的最终实现:不允许任何其他实现。
现在你还可以实现一个抽象类两次:
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("second abstractMethod()"); }
}
现在你可以在某处写另一个方法。
public tryItOut()
{
ImplementingClass a = new ImplementingClass();
AbstractClass b = new ImplementingClass();
a.abstractMethod(); // prints "abstractMethod()"
a.implementedMethod(); // prints "Overridden!" <-- same
a.finalMethod(); // prints "finalMethod()"
b.abstractMethod(); // prints "abstractMethod()"
b.implementedMethod(); // prints "Overridden!" <-- same
b.finalMethod(); // prints "finalMethod()"
SecondImplementingClass c = new SecondImplementingClass();
AbstractClass d = new SecondImplementingClass();
c.abstractMethod(); // prints "second abstractMethod()"
c.implementedMethod(); // prints "implementedMethod()"
c.finalMethod(); // prints "finalMethod()"
d.abstractMethod(); // prints "second abstractMethod()"
d.implementedMethod(); // prints "implementedMethod()"
d.finalMethod(); // prints "finalMethod()"
}
注意,尽管我们将b声明为AbstractClass类型,但它显示为“override !”。这是因为我们实例化的对象实际上是一个ImplementingClass,它的implementedMethod()当然被重写了。(您可能已经看到这被称为多态。)
如果希望访问特定于特定子类的成员,必须先向下转换到该子类:
// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();
最后,你不能做以下事情:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
一次只能扩展一个类。如果需要扩展多个类,则它们必须是接口。你可以这样做:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
下面是一个接口示例:
interface InterfaceA
{
void interfaceMethod();
}
这基本等同于:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
唯一的区别是第二种方法不会让编译器知道它实际上是一个接口。如果你想让人们只实现你的接口而不实现其他接口,这可能很有用。然而,作为初学者的经验法则,如果你的抽象类只有抽象方法,你可能应该让它成为一个接口。
以下行为是非法的:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
不能在接口中实现方法。这意味着如果实现两个不同的接口,这些接口中的不同方法不能冲突。由于接口中的所有方法都是抽象的,因此必须实现该方法,并且由于您的方法是继承树中唯一的实现,因此编译器知道它必须使用您的方法。
其他回答
它什么都不做,只是提供一个公共模板,它将被它的子类共享
An abstract class is one that isn't fully implemented but provides something of a blueprint for subclasses. It may be partially implemented in that it contains fully-defined concrete methods, but it can also hold abstract methods. These are methods with a signature but no method body. Any subclass must define a body for each abstract method, otherwise it too must be declared abstract. Because abstract classes cannot be instantiated, they must be extended by at least one subclass in order to be utilized. Think of the abstract class as the generic class, and the subclasses are there to fill in the missing information.
抽象类是不能被实例化的类。抽象类是通过创建可实例化的继承子类来使用的。抽象类为继承的子类做了一些事情:
定义可由继承子类使用的方法。 定义继承子类必须实现的抽象方法。 提供一个公共接口,允许子类与所有其他子类交换。
这里有一个例子:
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
注意,“abstractMethod()”没有任何方法主体。因此,你不能做以下事情:
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
没有实现abstractMethod()的方法!因此,当JVM获得像new ImplementingClass(). abstractmethod()这样的东西时,它无法知道应该做什么。
这是一个正确的实现类。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
注意,您不必定义implementedMethod()或finalMethod()。它们已经由AbstractClass定义。
这是另一个正确的ImplementingClass。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
在本例中,您重写了implementedMethod()。
但是,由于final关键字,不能执行以下操作。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
public void finalMethod() { System.out.print("ERROR!"); }
}
您不能这样做,因为AbstractClass中finalMethod()的实现被标记为finalMethod()的最终实现:不允许任何其他实现。
现在你还可以实现一个抽象类两次:
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("second abstractMethod()"); }
}
现在你可以在某处写另一个方法。
public tryItOut()
{
ImplementingClass a = new ImplementingClass();
AbstractClass b = new ImplementingClass();
a.abstractMethod(); // prints "abstractMethod()"
a.implementedMethod(); // prints "Overridden!" <-- same
a.finalMethod(); // prints "finalMethod()"
b.abstractMethod(); // prints "abstractMethod()"
b.implementedMethod(); // prints "Overridden!" <-- same
b.finalMethod(); // prints "finalMethod()"
SecondImplementingClass c = new SecondImplementingClass();
AbstractClass d = new SecondImplementingClass();
c.abstractMethod(); // prints "second abstractMethod()"
c.implementedMethod(); // prints "implementedMethod()"
c.finalMethod(); // prints "finalMethod()"
d.abstractMethod(); // prints "second abstractMethod()"
d.implementedMethod(); // prints "implementedMethod()"
d.finalMethod(); // prints "finalMethod()"
}
注意,尽管我们将b声明为AbstractClass类型,但它显示为“override !”。这是因为我们实例化的对象实际上是一个ImplementingClass,它的implementedMethod()当然被重写了。(您可能已经看到这被称为多态。)
如果希望访问特定于特定子类的成员,必须先向下转换到该子类:
// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();
最后,你不能做以下事情:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
一次只能扩展一个类。如果需要扩展多个类,则它们必须是接口。你可以这样做:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
下面是一个接口示例:
interface InterfaceA
{
void interfaceMethod();
}
这基本等同于:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
唯一的区别是第二种方法不会让编译器知道它实际上是一个接口。如果你想让人们只实现你的接口而不实现其他接口,这可能很有用。然而,作为初学者的经验法则,如果你的抽象类只有抽象方法,你可能应该让它成为一个接口。
以下行为是非法的:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
不能在接口中实现方法。这意味着如果实现两个不同的接口,这些接口中的不同方法不能冲突。由于接口中的所有方法都是抽象的,因此必须实现该方法,并且由于您的方法是继承树中唯一的实现,因此编译器知道它必须使用您的方法。
Java类在以下条件下变成抽象类:
1. 至少有一个方法被标记为abstract:
public abstract void myMethod()
在这种情况下,编译器会强制您将整个类标记为抽象类。
2. 该类被标记为abstract:
abstract class MyClass
如前所述:如果你有一个抽象方法,编译器会强迫你将整个类标记为抽象。但是即使你没有任何抽象方法,你仍然可以把类标记为抽象的。
常见的使用:
抽象类的一个常见用途是提供类的大纲,类似于接口。但与接口不同的是,它已经可以提供功能,即类的某些部分已经实现,而另一些部分只是用方法声明来概述。(“摘要”)
抽象类不能被实例化,但是可以基于抽象类创建具体类,然后可以实例化抽象类。要做到这一点,你必须继承抽象类并重写抽象方法,即实现它们。
使用abstract关键字声明的类称为抽象类。 抽象是一个隐藏数据实现细节,只向用户显示功能的过程。抽象让您关注对象做了什么,而不是它是如何做的。
抽象类的主要内容
An abstract class may or may not contain abstract methods.There can be non abstract methods. An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon), like this: ex : abstract void moveTo(double deltaX, double deltaY); If a class has at least one abstract method then that class must be abstract Abstract classes may not be instantiated (You are not allowed to create object of Abstract class) To use an abstract class, you have to inherit it from another class. Provide implementations to all the abstract methods in it. If you inherit an abstract class, you have to provide implementations to all the abstract methods in it.
声明抽象类 在声明期间在类之前指定abstract关键字将使其抽象。看看下面的代码:
abstract class AbstractDemo{ }
声明抽象方法 在声明过程中在方法之前指定abstract关键字将使方法抽象。看看下面的代码,
abstract void moveTo();//no body
为什么我们需要抽象类
In an object-oriented drawing application, you can draw circles, rectangles, lines, Bezier curves, and many other graphic objects. These objects all have certain states (for ex -: position, orientation, line color, fill color) and behaviors (for ex -: moveTo, rotate, resize, draw) in common. Some of these states and behaviors are the same for all graphic objects (for ex : fill color, position, and moveTo). Others require different implementation(for ex: resize or draw). All graphic objects must be able to draw or resize themselves, they just differ in how they do it.
对于抽象超类来说,这是一个完美的情况。您可以利用这些相似性,并将所有图形对象声明为继承自相同的抽象父对象(例如:GraphicObject),如下图所示。
首先,声明一个抽象类GraphicObject,以提供所有子类完全共享的成员变量和方法,例如当前位置和moveTo方法。GraphicObject还声明了抽象方法,如draw或resize,这些方法需要由所有子类实现,但必须以不同的方式实现。GraphicObject类看起来像这样:
abstract class GraphicObject {
void moveTo(int x, int y) {
// Inside this method we have to change the position of the graphic
// object according to x,y
// This is the same in every GraphicObject. Then we can implement here.
}
abstract void draw(); // But every GraphicObject drawing case is
// unique, not common. Then we have to create that
// case inside each class. Then create these
// methods as abstract
abstract void resize();
}
在子类中使用抽象方法 GraphicObject的每个非抽象子类,如Circle和Rectangle,必须为draw和resize方法提供实现。
class Circle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
class Rectangle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
在main方法中,你可以像这样调用所有的方法:
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
在Java中实现抽象的方法
在java中有两种实现抽象的方法
抽象类(0到100%) 接口(100%)
具有构造函数、数据成员、方法等的抽象类
abstract class GraphicObject {
GraphicObject (){
System.out.println("GraphicObject is created");
}
void moveTo(int y, int x) {
System.out.println("Change position according to "+ x+ " and " + y);
}
abstract void draw();
}
class Circle extends GraphicObject {
void draw() {
System.out.println("Draw the Circle");
}
}
class TestAbstract {
public static void main(String args[]){
GraphicObject grObj = new Circle ();
grObj.draw();
grObj.moveTo(4,6);
}
}
输出:
GraphicObject is created
Draw the Circle
Change position according to 6 and 4
记住两条规则:
如果类中抽象方法和具体方法都很少, 将其声明为抽象类。 如果类只有抽象方法,则将其声明为接口。
引用:
TutorialsPoint - Java抽象 Java抽象类方法 Java文档-抽象方法和类 JavaPoint - Java中的抽象类
推荐文章
- JavaFX应用程序图标
- Java:强/软/弱/幻影引用的区别
- 在序列化和反序列化期间JSON属性的不同名称
- 获取Android设备名称
- Gradle代理配置
- 如何获得具有已知资源名称的资源id ?
- 在Android上将字符串转换为整数
- 为什么“System.out。”println“工作在Android?
- 在Java中什么时候使用可变参数?
- Mockito的argumentCaptor的例子
- 我如何告诉Spring Boot哪个主类用于可执行jar?
- 如何将Java8流的元素添加到现有的列表中
- 在Java 8中是否可以转换流?
- 不区分大小写的字符串作为HashMap键
- 什么是maven中的“pom”打包?