Java中的抽象类
在 C++ 中,如果一个类至少有一个纯虚函数,那么这个类就变成了抽象的。与 C++ 不同,在Java中,一个单独的关键字abstract用于使类抽象。
Abstract 是一个Java修饰符,适用于Java中的类和方法,但不适用于变量。
插图:抽象类
abstract class Shape
{
int color;
// An abstract function
abstract void draw();
}
以下是关于Java中抽象类的一些重要观察。
- 无法创建抽象类的实例。
- 允许构造函数。
- 我们可以有一个没有任何抽象方法的抽象类。
- 抽象类中可以有最终方法,但类(抽象类)中的任何抽象方法都不能声明为最终方法,或者简单地说,最终方法本身不能是抽象的,因为它会产生错误:“修饰符的非法组合:抽象和最终”
- 我们不允许为任何抽象类创建对象。
- 我们可以在抽象类中定义静态方法
- 我们可以使用 abstract 关键字将顶级类(外部类)以及内部类声明为抽象
- 如果一个类至少包含一个抽象方法,那么我们应该将类声明为抽象类
- 如果子类无法为父类的所有抽象方法提供实现,那么我们应该将该子类声明为抽象类,以便下一级子类应该为剩余的抽象方法提供实现
让我们详细说明这些观察结果,并在干净的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抽象类中的构造函数