📜  Java中的抽象类

📅  最后修改于: 2022-05-13 01:55:10.983000             🧑  作者: Mango

Java中的抽象类

在 C++ 中,如果一个类至少有一个纯虚函数,那么这个类就变成了抽象的。与 C++ 不同,在Java中,一个单独的关键字abstract用于使类抽象。

Abstract 是一个Java修饰符,适用于Java中的类和方法,但不适用于变量。

插图:抽象类

abstract class Shape 
{
    int color;

    // An abstract function
    abstract void draw();
}

以下是关于Java中抽象类的一些重要观察。

  1. 无法创建抽象类的实例。
  2. 允许构造函数。
  3. 我们可以有一个没有任何抽象方法的抽象类。
  4. 抽象类中可以有最终方法,但类(抽象类)中的任何抽象方法都不能声明为最终方法,或者简单地说,最终方法本身不能是抽象的,因为它会产生错误:“修饰符的非法组合:抽象和最终”
  5. 我们不允许为任何抽象类创建对象。
  6. 我们可以在抽象类中定义静态方法
  7. 我们可以使用 abstract 关键字将顶级类(外部类)以及内部类声明为抽象
  8. 如果一个类至少包含一个抽象方法,那么我们应该将类声明为抽象类
  9. 如果子类无法为父类的所有抽象方法提供实现,那么我们应该将该子类声明为抽象类,以便下一级子类应该为剩余的抽象方法提供实现

让我们详细说明这些观察结果,并在干净的Java程序的帮助下证明它们的正确性,如下所示。

观察 1:在Java中,很可能在 C++ 中无法创建抽象类的实例,但我们可以引用抽象类类型。通过干净的Java程序如下所示。

例子

Java
// Java Program to Illustrate That an instance of Abstract
// Class Can not be created
 
// Class 1
// Abstract class
abstract class Base {
    abstract void fun();
}
 
// Class 2
class Derived extends Base {
    void fun()
    {
        System.out.println("Derived fun() called");
    }
}
 
// Class 3
// Main class
class Main {
 
    // Main driver method
    public static void main(String args[])
    {
 
        // Uncommenting the following line will cause
        // compiler error as the line tries to create an
        // instance of abstract class. Base b = new Base();
 
        // We can have references of Base type.
        Base b = new Derived();
        b.fun();
    }
}


Java
// Java Program to Illustrate Abstract Class
// Can contain Constructors
 
// Class 1
// Abstract class
abstract class Base {
 
    // Constructor of class 1
    Base()
    {
        // Print statement
        System.out.println("Base Constructor Called");
    }
 
    // Abstract method inside class1
    abstract void fun();
}
 
// Class 2
class Derived extends Base {
 
    // Constructor of class2
    Derived()
    {
        System.out.println("Derived Constructor Called");
    }
 
    // Method of class2
    void fun()
    {
        System.out.println("Derived fun() called");
    }
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
        // Creating object of class 2
        // inside main() method
        Derived d = new Derived();
    }
}


Java
// Java Program to illustrate Abstract class
// Without any abstract method
 
// Class 1
// An abstract class without any abstract method
abstract class Base {
 
    // Demo method
    void fun()
    {
        // Print message if class 1 function is called
        System.out.println(
            "Function of Base class is called");
    }
}
 
// Class 2
class Derived extends Base {
}
 
// Class 3
class Main {
 
    // Main driver method
    public static void main(String args[])
    {
        // Creating object of class 2
        Derived d = new Derived();
 
        // Calling function defined in class 1 inside main()
        // with object of class 2 inside main() method
        d.fun();
    }
}


Java
// Java Program to Illustrate Abstract classes
// Can also have Final Methods
 
// Class 1
// Abstract class
abstract class Base {
 
    final void fun()
    {
        System.out.println("Base fun() called");
    }
}
 
// Class 2
class Derived extends Base {
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
 
        // Creating object of abstract class
        Base b = new Derived();
 
        // Calling method on object created above
        // inside main()
        b.fun();
    }
}


Java
// Java Program to Illustrate Abstract Class
 
// Main class
// An abstract class
abstract class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
 
        // Trying to create an object
        GFG gfg = new GFG();
    }
}


Java
// Java Program to Illustrate Static Methods in Abstract
// Class Can be called Independently
 
// Class 1
// Abstract class
abstract class Helper {
 
    // Abstract method
    static void demofun()
    {
 
        // Print statement
        System.out.println("Geeks for Geeks");
    }
}
 
// Class 2
// Main class extending Helper class
public class GFG extends Helper {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Calling method inside main()
        // as defined in above class
        Helper.demofun();
    }
}


Java
/*package whatever //do not write package name here */
 
import java.io.*;
 
abstract class B {
  //declaring inner class as abstract with abstract method
    abstract class C {
        abstract void myAbstractMethod();
    }
}
class D extends B {
    class E extends C {
      // implementing the abstract method
        void myAbstractMethod() { System.out.println("Inside abstract method implementation"); }
    }
}
 
public class Main {
 
    public static void main(String args[])
    {
        // Instantiating the outer class
        D outer = new D();
 
        // Instantiating the inner class
        D.E inner = outer.new E();
        inner.myAbstractMethod();
    }
}


Java
/*package whatever //do not write package name here */
 
import java.io.*;
 
// here if we remove the abstract keyword then we will get
// compile time error due to abstract method
abstract class Demo {
    abstract void m1();
}
 
class Child extends Demo {
    public void m1()
    {
      System.out.print("Hello");
    }
}
class GFG {
    public static void main(String[] args)
    {
        Child c = new Child();
        c.m1();
    }
}


Java
/*package whatever //do not write package name here */
 
import java.io.*;
abstract class Demo {
    abstract void m1();
    abstract void m2();
    abstract void m3();
}
abstract class FirstChild extends Demo {
    public void m1() { System.out.println("Inside m1"); }
}
 
class SecondChild extends FirstChild {
    public void m2() { System.out.println("Inside m2"); }
    public void m3() { System.out.println("Inside m3"); }
}
class GFG {
    public static void main(String[] args)
    {
        // if we remove the abstract keyword from FirstChild
        // Class and uncommented below obj creation for
        // FirstChild then it will throw
        // compile time error as did't override all the
        // abstract methods
 
        // FirstChild f=new FirstChild();
        // f.m1();
 
        SecondChild s = new SecondChild();
        s.m1();
        s.m2();
        s.m3();
    }
}


输出
Derived fun() called

观察 2:与 C++ 一样,抽象类可以包含Java中的构造函数。并且在创建继承类的实例时调用抽象类的构造函数。如下程序所示:

例子

Java

// Java Program to Illustrate Abstract Class
// Can contain Constructors
 
// Class 1
// Abstract class
abstract class Base {
 
    // Constructor of class 1
    Base()
    {
        // Print statement
        System.out.println("Base Constructor Called");
    }
 
    // Abstract method inside class1
    abstract void fun();
}
 
// Class 2
class Derived extends Base {
 
    // Constructor of class2
    Derived()
    {
        System.out.println("Derived Constructor Called");
    }
 
    // Method of class2
    void fun()
    {
        System.out.println("Derived fun() called");
    }
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
        // Creating object of class 2
        // inside main() method
        Derived d = new Derived();
    }
}
输出
Base Constructor Called
Derived Constructor Called

观察 3:在Java中,我们可以有一个没有任何抽象方法的抽象类。这允许我们创建不能被实例化但只能被继承的类。在干净的Java程序的帮助下如下所示。

例子

Java

// Java Program to illustrate Abstract class
// Without any abstract method
 
// Class 1
// An abstract class without any abstract method
abstract class Base {
 
    // Demo method
    void fun()
    {
        // Print message if class 1 function is called
        System.out.println(
            "Function of Base class is called");
    }
}
 
// Class 2
class Derived extends Base {
}
 
// Class 3
class Main {
 
    // Main driver method
    public static void main(String args[])
    {
        // Creating object of class 2
        Derived d = new Derived();
 
        // Calling function defined in class 1 inside main()
        // with object of class 2 inside main() method
        d.fun();
    }
}
输出
Function of Base class is called

观察 4:抽象类也可以有最终方法(不能被覆盖的方法)

例子

Java

// Java Program to Illustrate Abstract classes
// Can also have Final Methods
 
// Class 1
// Abstract class
abstract class Base {
 
    final void fun()
    {
        System.out.println("Base fun() called");
    }
}
 
// Class 2
class Derived extends Base {
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
 
        // Creating object of abstract class
        Base b = new Derived();
 
        // Calling method on object created above
        // inside main()
        b.fun();
    }
}
输出
Base fun() called

观察 5:对于任何抽象Java类,我们都不允许创建对象,即,抽象类实例化是不可能的。

例子

Java

// Java Program to Illustrate Abstract Class
 
// Main class
// An abstract class
abstract class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
 
        // Trying to create an object
        GFG gfg = new GFG();
    }
}

输出:

观察 6:与接口类似,我们可以在抽象类中定义静态方法,无需对象即可独立调用。

例子

Java

// Java Program to Illustrate Static Methods in Abstract
// Class Can be called Independently
 
// Class 1
// Abstract class
abstract class Helper {
 
    // Abstract method
    static void demofun()
    {
 
        // Print statement
        System.out.println("Geeks for Geeks");
    }
}
 
// Class 2
// Main class extending Helper class
public class GFG extends Helper {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Calling method inside main()
        // as defined in above class
        Helper.demofun();
    }
}
输出
Geeks for Geeks

观察 7:我们可以使用 abstract 关键字将顶级类(外部类)以及内部类声明为抽象

Java

/*package whatever //do not write package name here */
 
import java.io.*;
 
abstract class B {
  //declaring inner class as abstract with abstract method
    abstract class C {
        abstract void myAbstractMethod();
    }
}
class D extends B {
    class E extends C {
      // implementing the abstract method
        void myAbstractMethod() { System.out.println("Inside abstract method implementation"); }
    }
}
 
public class Main {
 
    public static void main(String args[])
    {
        // Instantiating the outer class
        D outer = new D();
 
        // Instantiating the inner class
        D.E inner = outer.new E();
        inner.myAbstractMethod();
    }
}

输出:

Inside abstract method implementation

观察 8:如果一个类至少包含一个抽象方法,那么我们应该将类声明为抽象类,否则我们将得到编译时错误,因为如果一个类包含至少一个抽象方法,那么该类的实现是不完整的,因此它不是建议创建一个对象,因此为了限制此类部分类的对象创建,我们使用抽象关键字

Java

/*package whatever //do not write package name here */
 
import java.io.*;
 
// here if we remove the abstract keyword then we will get
// compile time error due to abstract method
abstract class Demo {
    abstract void m1();
}
 
class Child extends Demo {
    public void m1()
    {
      System.out.print("Hello");
    }
}
class GFG {
    public static void main(String[] args)
    {
        Child c = new Child();
        c.m1();
    }
}

输出:

Hello

观察 9:如果子类无法为父类的所有抽象方法提供实现,那么我们应该将该子类声明为抽象类,以便下一级子类应该为剩余的抽象方法提供实现

Java

/*package whatever //do not write package name here */
 
import java.io.*;
abstract class Demo {
    abstract void m1();
    abstract void m2();
    abstract void m3();
}
abstract class FirstChild extends Demo {
    public void m1() { System.out.println("Inside m1"); }
}
 
class SecondChild extends FirstChild {
    public void m2() { System.out.println("Inside m2"); }
    public void m3() { System.out.println("Inside m3"); }
}
class GFG {
    public static void main(String[] args)
    {
        // if we remove the abstract keyword from FirstChild
        // Class and uncommented below obj creation for
        // FirstChild then it will throw
        // compile time error as did't override all the
        // abstract methods
 
        // FirstChild f=new FirstChild();
        // f.m1();
 
        SecondChild s = new SecondChild();
        s.m1();
        s.m2();
        s.m3();
    }
}

输出:

Inside m1
Inside m2
Inside m3

必读:

  • Java中抽象类和接口的区别
  • 抽象类和抽象方法之间的区别
  • Java抽象类中的构造函数