Java基础之抽象类和接口

181 阅读3分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」​

一、抽象类

1、Abstract(抽象)可以修饰类、方法 

如果将一个类声明为abstract,此类不能生成对象,只能被继承使用。

Abstract类的设计是将子类的共性最大限度的抽取出来,以提高程序的统一性。

2、一个类中包含有抽象方法必须声明为抽象类;

如果一个类中有一个抽象方法,那么这个类一定为一个抽象类。

反之,如果一个类为抽象类,那么其中可能有非抽象的方法。

3、抽象类不能实例化,但仍可以声明;

Abstract类可以作为编译时类型,但不能作为运行时类型。

4、子类继承抽象类必须实现其中抽象方法

当abstract用于修饰方法时,此时该方法为抽象方法,此时方法不需要实现,实现留给子类覆盖,子类覆盖该方法之后方法才能够生效。

注意比较:

private void print(){};此语句表示方法的空实现。

Abstract void print(); 此语句表示方法的抽象,无实现

二、 接口 (模板方法模式)

  1. 接口是抽象类的另外一种形式(没有实例变量的抽象类);

  2. 在一个接口中所有方法都是抽象方法;

  3. 接口中所有变量都必须被定义为final static; 

  4. 接口可以继承多个接口。

  5. 可插入性的保障――工程模式

  6. 是规范的制订者和规范的实现者分开。――JDBC

注:1) 接口中的方法自动被置为public, 因经,在接口中声明方法并不需要提供public关键字。但在实现接口时,必须把方法声明为public。

接口与抽象类的区别:

接口                                                        抽象类

无实现方法                                          可以有非抽象方法――实现代码

可以把子类的共有代码

提取出来放在抽象类中

在JAVA中的接口分类:

         普通         -----有方法和属性

         常量         -----存常量

         标记   -----没有方法,属性,只为了做编译类型的标记

实例:

简单工厂模式(接口和多态的实际使用)

public interface Car {

         public void brake();

         public void grade();

         public void engineer();

        

}

public class BMW implements Car{

         private String name;

        

         public String getName() {

                   return name;

         }

         public void setName(String name) {

                   this.name = name;

         }

         public void brake() {

                   // TODO Auto-generated method stub

                   System.out.println("BMWcar's brake()");

         }

         public void engineer() {

                   // TODO Auto-generated method stub

                   System.out.println("BMWcar's engieer()");

         }

         public void grade() {

                   // TODO Auto-generated method stub

                   System.out.println("BMWcar's greade()");

         }

         /**

          * @param args

          */

}

Public class Banz implements Car{

         ……

}

Public class Factory{

         Public static Car factory(String name){

                   If(name.equals(“BMW”){

                            Return new BMWCar(); //返回一个引用

                   }

                   If(name.equals(“Banz”){

                            Return new BanzCar();

                   }

         }

}

注意:

1 这个问题不是对象有没有toString方法的问题,而是用接口作为编译时类型能否调用的问题.

2 接口就是接口,尽管本质上是抽象类,但是总归不是类,接口没有父类,Object类绝不是接口的父类,这种理解大错而特错!!!

三、我们来看看虚拟机规范是怎么说的

 JVM会解析类型为CONSTANT_InterfaceMethodref_info的常量池的入口,会按照如下步骤执行接口方法解析:

 1) 检查接口是否具有用户调用的方法

 2) 检查接口的父接口是否具有用户调用的方法

 3) 检查java.lang.Object是否具有用户调用的方法

 4) 抛出NoSuchMethodException

因此,不是接口类型有toString方法,用反射是看不到这个方法的,而是虚拟机在作方法调用连接时,会自动去找Object类中的方法.虚拟机就是这么工作的所以,对以接口作为编译时类型的方法调用,根据以上说的第三点,Object类中的方法都可以得到调用