Java中的抽象类

什么是Java中的“抽象类”?

抽象类是一个不能被实例化的类。 通过创build一个可以实例化的inheritance子类来使用抽象类。 抽象类为inheritance子类做了一些事情:

  1. 定义inheritance子类可以使用的方法。
  2. 定义inheritance子类必须实现的抽象方法。
  3. 提供一个通用接口,允许子类与其他所有子类互换。

这是一个例子:

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()这样的东西时,JVM就无法知道应该做什么了。

这是一个正确的ImplementingClass

 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!"); } } 

您不能这样做,因为AbstractClassfinalMethod()的实现被标记为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()" } 

请注意,尽pipe我们声明bAbstractClasstypes,但它显示"Overriden!" 。 这是因为我们实例化的对象实际上是一个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!"); } } 

你不能在接口中实现方法。 这意味着如果你实现了两个不同的接口,这些接口中的不同方法是不能碰撞的。 由于接口中的所有方法都是抽象的,所以你必须实现这个方法,而且由于你的方法是inheritance树中的唯一实现,所以编译器知道它必须使用你的方法。

Java类在以下条件下变为抽象:

1.至less有一种方法被标记为抽象:

 public abstract void myMethod() 

在这种情况下,编译器迫使你把整个类标记为抽象的。

2.这个类被标记为抽象的:

 abstract class MyClass 

正如已经说过的那样:如果你有一个抽象的方法,编译器会迫使你把整个类标记为抽象的。 但即使你没有抽象的方法,你仍然可以把这个类标记为抽象的。

常用:

抽象类的一个常见用途是提供类似于类似接口的类的轮廓。 但是与接口不同的是它已经可以提供function,也就是类的某些部分被实现了,一些部分只是用方法声明来概述。 (“抽象”)

一个抽象类不能被实例化,但是你可以创build一个基于抽象类的具体类,然后它可以被实例化。 为此,您必须从抽象类inheritance并重写抽象方法,即实现它们。

这是一个无法实例化的类,并强制实现类,可能会实现它概述的抽象方法。

从oracle 文档

抽象方法和类:

抽象类是一个被声明为抽象类的类,它可能包含也可能不包含抽象方法

抽象类不能被实例化,但可以被分类

抽象方法是一个没有实现(没有大括号,后跟分号)的方法,如下所示:

 abstract void moveTo(double deltaX, double deltaY); 

如果一个类包含抽象方法,那么该类本身必须声明为抽象的,如下所示:

 public abstract class GraphicObject { // declare fields // declare nonabstract methods abstract void draw(); } 

当抽象类是子类时,子类通常为其父类中的所有抽象方法提供实现。 但是,如果没有,那么子类也必须被声明为抽象的

由于abstract classesinterfaces是相关的,请看下面的SE问题:

界面和抽象类有什么区别?

我应该如何解释一个接口和一个抽象类的区别?

在这里得到你的答案:

Java中的抽象类与接口

抽象类可以有最终的方法吗?

顺便说一句 – 那些是你最近问的问题。 想想一个新的问题来build立声誉…

编辑:

刚刚意识到,这个和参考问题的海报有相同或至less相似的名字,但用户ID总是不同的。 因此,无论是技术上的问题,keyur都有问题再次login,find问题的答案,或者这是一种娱乐SO社区的游戏;)

使用abstract关键字声明的abstract class被称为abstract class 。 抽象是隐藏数据实现细节的过程,只向用户显示function。 抽象让你专注于对象的作用,而不是它如何做。

抽象类的主要事物

  • 抽象类可能包含或不包含抽象方法。可能有非抽象方法。

    抽象方法是一个没有实现(没有大括号,后跟分号)的方法,如下所示:

    例如: abstract void moveTo(double deltaX, double deltaY);

  • 如果一个类至less有一个抽象方法,那么这个类必须是抽象的

  • 抽象类可能不会被实例化(您不能创buildAbstract类的对象)

  • 要使用抽象类,必须从另一个类inheritance它。 为其中的所有抽象方法提供实现。

  • 如果你inheritance了一个抽象类,你必须为其中的所有抽象方法提供实现。

声明抽象类在声明期间在类之前指定abstract关键字使其变为抽象。 看看下面的代码:

 abstract class AbstractDemo{ } 

声明抽象方法在声明期间在方法之前指定abstract关键字使其变为抽象。 看看下面的代码,

 abstract void moveTo();//no body 

为什么我们需要抽象类

在面向对象的绘图应用程序中,您可以绘制圆形,矩形,线条,贝塞尔曲线和许多其他graphics对象。 这些对象都具有共同的某些状态(例如:位置,方向,线条颜色,填充颜色)和行为(例如:moveTo,rotate,resize,draw)。 其中一些状态和行为对于所有graphics对象是相同的(例如:填充颜色,位置和moveTo)。 其他需要不同的实现(例如:resize或绘制)。 所有的graphics对象必须能够绘制或调整自己的大小,他们只是不同的方式。

这对抽象超类来说是一个完美的情况。 您可以利用相似性,并声明所有graphics对象从相同的抽象父对象(例如: GraphicObject )inheritance,如下图所示。 在这里输入图像描述

首先,您声明一个抽象类GraphicObject ,以提供由所有子类完全共享的成员variables和方法,例如当前位置和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每个非抽象子类(如CircleRectangle )都必须为GraphicObjectGraphicObject方法提供实现。

 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 

记住两条规则:

  • 如果这个类抽象方法很less,具体的方法很less,那么就把它声明为一个abstract类。

  • 如果该类只有抽象方法,则将其声明为interface

参考文献:

  • TutorialsPoint – Java抽象
  • BeginnersBook – Java抽象类方法
  • Java文档 – 抽象方法和类
  • JavaPoint – Java中的抽象类

简而言之,您可以将抽象类看作一个具有更多function的接口。

你不能实例化一个接口,这也适用于抽象类。

在你的界面上,你可以定义方法头文件,所有的实现者都被迫实现所有的头文件。 在一个抽象类中,你也可以定义你的方法头,但是在这里 – 对于接口的区别 – 你也可以定义方法的主体(通常是一个默认实现)。 而且,当其他类扩展(注意,不实现,因此每个子类也只能有一个抽象类 )时,它们不会被强制实现抽象类的所有方法,除非指定了抽象方法在这种情况下,它像接口一样工作,你不能定义方法主体)。

 public abstract class MyAbstractClass{ public abstract void DoSomething(); } 

否则,对于抽象类的普通方法,“inheritance者”可以像平常一样使用默认行为或重写它。

例:

 public abstract class MyAbstractClass{ public int CalculateCost(int amount){ //do some default calculations //this can be overriden by subclasses if needed } //this MUST be implemented by subclasses public abstract void DoSomething(); } 

一个抽象类不能直接实例化,但必须派生出来才能使用。 一个类必须是抽象的,如果它包含抽象方法:直接

 abstract class Foo { abstract void someMethod(); } 

或间接

 interface IFoo { void someMethod(); } abstract class Foo2 implements IFoo { } 

但是,一个类可以是抽象的而不包含抽象方法。 它是一种防止直接的瞬时的方式,例如

 abstract class Foo3 { } class Bar extends Foo3 { } Foo3 myVar = new Foo3(); // illegal! class is abstract Foo3 myVar = new Bar(); // allowed! 

后者抽象类的风格可以用来创build“类接口”类。 与接口不同,抽象类可以包含非抽象方法和实例variables。 您可以使用它来提供一些基本function来扩展类。

另一种常见的模式是在抽象类中实现主要function,并在抽象方法中定义部分algorithm,由扩展类来实现。 愚蠢的例子:

 abstract class Processor { protected abstract int[] filterInput(int[] unfiltered); public int process(int[] values) { int[] filtered = filterInput(values); // do something with filtered input } } class EvenValues extends Processor { protected int[] filterInput(int[] unfiltered) { // remove odd numbers } } class OddValues extends Processor { protected int[] filterInput(int[] unfiltered) { // remove even numbers } } 

解决scheme – 基类(抽象)

 public abstract class Place { String Name; String Postcode; String County; String Area; Place () { } public static Place make(String Incoming) { if (Incoming.length() < 61) return (null); String Name = (Incoming.substring(4,26)).trim(); String County = (Incoming.substring(27,48)).trim(); String Postcode = (Incoming.substring(48,61)).trim(); String Area = (Incoming.substring(61)).trim(); Place created; if (Name.equalsIgnoreCase(Area)) { created = new Area(Area,County,Postcode); } else { created = new District(Name,County,Postcode,Area); } return (created); } public String getName() { return (Name); } public String getPostcode() { return (Postcode); } public String getCounty() { return (County); } public abstract String getArea(); } 

抽象类的6个要点[Java]:

在这里输入图像描述

在这里输入图像描述

在这里输入图像描述

所有这些职位除外。

有时你可能想声明一个类,但不知道如何定义属于该类的所有方法。 例如,您可能想要声明一个名为Writer的类,并在其中包含一个名为write()的成员方法。 但是,您不知道如何编写write(),因为每种Writer设备都不相同。 当然,你打算通过派生Writer的子类来处理这个问题,比如打印机,磁盘,networking和控制台。

可以既具体又非具体的方法,即与身体和无身体的类。 没有实现的1方法必须包含“抽象”关键字2抽象类不能被实例化

抽象类是一个被声明为抽象的类 – 它可能包含也可能不包含抽象方法。 抽象类不能被实例化,但它们可以被子类化。

换句话说,一个用abstract关键字声明的类在java中被称为抽象类。 它可以有抽象(无主体的方法)和非抽象的方法(有主体的方法)。

重要的注意事项: –抽象类不能用于实例化对象,它们可以用来创build对象引用,因为Java的运行时多态的方法是通过使用超类引用来实现的。 因此,必须可以创build一个对抽象类的引用,以便它可以用来指向一个子类对象。 您将在下面的示例中看到此function

 abstract class Bike{ abstract void run(); } class Honda4 extends Bike{ void run(){ System.out.println("running safely.."); } public static void main(String args[]){ Bike obj = new Honda4(); obj.run(); } } 

class级成员

抽象类可能有静态字段和静态方法。 您可以像使用任何其他类一样将这些静态成员与类引用(例如AbstractClass.staticMethod())一起使用。

不要忘记这一点。

抽象类是一个没有完全实现的类,但为子类提供了一些蓝图。 它可能是部分实现的,因为它包含完全定义的具体方法,但也可以包含抽象方法。 这些是带有签名但没有方法体的方法。 任何子类都必须为每个抽象方法定义一个主体,否则也必须声明为抽象。 因为抽象类不能被实例化,所以它们必须被至less一个子类扩展才能被使用。 把抽象类看作generics类,然后用子类来填充缺失的信息。