📜  Java抽象类和具体类的区别

📅  最后修改于: 2021-09-11 03:39:28             🧑  作者: Mango

抽象类:抽象类是Java中的一种类,由abstract关键字声明。抽象类不能直接实例化,即不能直接使用 new 关键字创建此类的对象。抽象类可以通过具体子类或通过定义所有抽象方法以及 new 语句来实例化。它可能包含也可能不包含抽象方法。抽象方法由abstract关键字声明,这样的方法不能有主体。如果一个类包含一个抽象方法,那么它也需要是抽象的。

具体类: Java中的具体类是一种子类,它实现了它所扩展到的超抽象类的所有抽象方法。它还具有它实现的所有接口方法的实现。

抽象类与具体类

  1. 修饰符:使用抽象修饰符声明抽象类。不应使用抽象关键字声明具体类,否则它也会成为抽象类。
  2. 实例化:抽象类不能直接实例化,即不能直接使用new关键字创建该类的对象。抽象类可以通过具体子类或通过定义所有抽象方法以及 new 语句来实例化。可以使用 new 关键字直接实例化具体类。
    示例:抽象类的直接实例化无效。
    abstract class DemoAbstractClass {
        abstract void display();
    }
      
    public class JavaApplication {
        public static void main(String[] args)
        {
            DemoAbstractClass AC = new DemoAbstractClass();
            System.out.println("Hello");
        }
    }
    

    编译错误:

    prog.java:9: error: DemoAbstractClass is abstract; cannot be instantiated
            DemoAbstractClass AC = new DemoAbstractClass();
                                   ^
    

    示例:通过定义抽象类的所有抽象方法进行有效实例化。

    abstract class DemoAbstractClass {
        abstract void display();
    }
      
    public class JavaApplication {
        public static void main(String[] args)
        {
            DemoAbstractClass AC = new DemoAbstractClass() {
                void display()
                {
                    System.out.println("Hi.");
                }
            };
            AC.display();
            System.out.println("How are you?");
        }
    }
    
    输出:
    Hi.
    How are you?
    

    示例:使用 new 关键字直接实例化混凝土。

    abstract class DemoAbstractClass {
        abstract void display();
    }
      
    class ConcreteClass extends DemoAbstractClass {
        void display()
        {
            System.out.println("Hi.");
        }
    }
      
    public class JavaApplication {
        public static void main(String[] args)
        {
            ConcreteClass C = new ConcreteClass();
            C.display();
            System.out.println("How are you?");
        }
    }
    
    输出:
    Hi.
    How are you?
    
  3. 抽象方法:抽象类可能有也可能没有抽象方法。具体类不能有抽象方法,因为包含抽象方法的类也必须是抽象的。
    让我们通过一个例子来理解这一点:-
    我们在 Servlet 中有一个名为“HttpServlet”的类。现在,这个类有自己的特殊性。
    “HttpServlet 是一个抽象类,但它不包含任何抽象方法”。
    让我们深入理解上述语句的含义:-
    -> HttpServlet 是一个抽象类,因为它的方法没有正确的实现。既然它的方法没有正确的实现,那么为这样的类创建对象有什么意义。因此,这个类是抽象的。

    现在出现的问题是:-
    问:如果方法没有正确的实现,那为什么不把它抽象化?
    -> 因为抽象方法是那些没有适当的主体定义的方法,我们在我们的类中覆盖这些方法来给它一个适当的定义。所以基本上抽象方法用于覆盖目的。
    现在这个“HttpServlet”类包含 10 个方法,假设如果这些方法是抽象的,那么我们需要覆盖“HttpServlet”类的所有 10 个方法,这是一种愚蠢的方法,因为我们只需要 doGet() 和 doPost() 方法。

    下面是一个示例程序,用于在Java说明上述观点:

    // Java program to show servlet example
    // Importing required Java libraries
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
      
    // Extend HttpServlet class
    public class AdvanceJavaConcepts
        extends HttpServlet {
        private String output;
      
        // Initializing servelet
        public void init() throws ServletException
        {
            output = "Advance Java Concepts";
        }
      
        // Requesting and printing the output
        public void doGet(HttpServletRequest req,
                          HttpServletResponse resp)
            throws ServletException, IOException
        {
            resp.setContentType("text/html");
            PrintWriter out = resp.getWriter();
            out.println(output);
        }
      
        public void destroy()
        {
            System.out.println("Over");
        }
    }
    

    输出:

    Advance Java Concepts
    output
    Over
    

    注意:如前所述,HttpServlet 类不包含任何抽象方法。因此程序成功运行而不会覆盖其所有方法。
    但是假设如果这个类包含它所有的抽象方法,那么我们需要覆盖它的所有方法,尽管它们在我们的类中什么都不做。
    HttpServlet 类的方法原型为:

    1. 公共无效服务(ServletRequest req, ServletResponse res)
    2. 受保护的无效服务(HttpSerletRequest req,HttpServletResponse res)
    3. protected void doGet(HttpSerletRequest req, HttpServletResponse res)
    4. protected void doPost(HttpSerletRequest req, HttpServletResponse res)
    5. protected void doHead(HttpSerletRequest req, HttpServletResponse res)
    6. protected void doOptions(HttpSerletRequest req, HttpServletResponse res)
    7. protected void doPut(HttpSerletRequest req, HttpServletResponse res)
    8. protected void doTrace(HttpSerletRequest req, HttpServletResponse res)
    9. protected void doDelete(HttpSerletRequest req, HttpServletResponse res)
    10. protected void getLastModified(HttpSerletRequest req)

    如果我们的类是抽象的,那么这些方法的不必要覆盖就会出现在我们的类中。

    注意:但是在 NetBeans 等最新的 IDE 中,它会自动覆盖所有抽象方法,为它们提供空白主体,减少程序员重写的麻烦。

  4. Final:抽象类不能是final ,因为它的所有抽象方法都必须在子类中定义。具体类可以声明为final
  5. 接口:抽象类不能单独实现接口,但可以通过使用子类而不提供接口所有方法的实现来实现接口。以抽象类为祖先的第一个具体类负责实现接口中的所有方法。
Abstract Class Concrete Class
An abstract class is declared using abstract modifier. A concrete class is note declared using abstract modifier.
An abstract class cannot be directly instantiated using the new keyword. A concrete class can be directly instantiated using the new keyword.
An abstract class may or may not contain abstract methods. A concrete class cannot contain an abstract method.
An abstract class cannot be declared as final. A concrete class can be declared as final.
Implement an interface is possible by not providing implementations of all of the interface’s methods. For this a child class is needed.. Easy implementation of all of the methods in the interface.

一些要点:

  • 具体类是抽象类的子类,抽象类实现了它的所有抽象方法。
  • 抽象方法不能有主体。
  • 抽象类可以像其他类一样有静态字段和静态方法。
  • 抽象类不能声明为 final。
  • 只有抽象类可以有抽象方法。
  • 私有的、最终的、静态的方法不能是抽象的,因为它不能在子类中被覆盖。
  • 抽象类不能有抽象构造函数。
  • 抽象类不能有抽象静态方法。
  • 如果一个类扩展了一个抽象类,那么它应该定义基础抽象类的所有抽象方法(覆盖)。如果不是,则子类(扩展抽象类的类)也必须定义为抽象类。