彻底搞定接口与抽象类

631 阅读3分钟

抽象类(Abstract Class)

在Java编程思想(第四版)中,这样定义抽象类的:包含抽象方法的类为抽象类,但是实际上如果一个类是抽象类,也可以没有抽象方法(一般不会这样子,没有什么意义)。

  • 如果继承了抽象类,则需要实现抽象类中未实现的抽象方法,如果没有抽象方法没有全部实现的话,则该类也必须是抽象方法,否则编译无法通过而报错
  • 抽象方法不能使用private修饰符,也==不宜==使用默认修饰符(default),如果使用默认修饰符(即缺省),那么其他的包即使继承了该抽象类,也无法重写该抽象方法
  • 抽象类方法默认权限修饰符为public
    • JDK 1.8以前,抽象类的方法默认访问权限为 protected
    • JDK 1.8时,抽象类的方法默认访问权限变为 default
  • 抽象类不能创建对象
  • 抽象类不一定包含抽象方法
  • 抽象类中,可以有构造方法,是供子类创建对象时候使用的,子类的构造方法中,第一行默认调用了super(),即访问父类的构造方法
  • 抽象方法权限修饰符必须为public或protected

抽象类总结:

如果不带修饰符,那么就是包内访问。这种情况下,不一定能保证对子类可见。如果子类和父类不在一个包下面,子类是无法访问(无法覆盖)父类的抽象方法。因此,abstract方法的访问权限==不应该==是包内访问。

所以对于abstract方法,不能使用private修饰符(导致编译出错),不能使用default修饰符(编译正常,但是不合理,后患无穷),可以使用public和protected,大多数情况下都是使用public。

接口(Interface)

接口定义:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法 (JDK 9)

如果一个抽象类没有字段,所有方法全部都是抽象方法,就可以把该抽象类改写为接口

public interface 接口名称 {
	// 抽象方法
	// 默认方法 JDK8
	// 静态方法 JDK8
	// 私有方法 JDK9
}
  • 接口不能创建对象,但是可以被实现(implements)

  • Java中,一个类只能继承一个类,而一个类可以实现多个接口,不同接口名用逗号隔开

    class Student implements Person, Child { // 实现了两个interface接口
        ...
    }
    
  • 接口之间可以相互继承,用extends继承接口

    /**
     * Description: 这个接口是父接口
     */
    public interface InterfaceBase {
        /**
         * 测试函数
         */
        public int test1();
    }
    
    
    /**
     * Description:定义子接口
     */
    public interface InterfaceSub extends InterfaceBase {
        /**
         * 子接口扩充新方法
         */
        public int test2();
    }
    
  • 接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误)

  • 接口的修饰符有public、abstract、default(JDK8)、static(JDK8)

  • 如果只写返回值类型 方法名称();那么默认使用修饰符public abstract

  • 默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。

    • 默认方法不能够重写Object 基类中的方法,但却可以重载Object基类中的方法
    • example:toString、equals、 hashCode 不能在接口中被覆盖,可以被重载
  • 静态方法:使用 static 修饰,供接口直接调用。在实现类中可以直接调用接口的default方法,通过接口名.方法名调用static方法

    /**
         * 测试接口
         */
    public interface InterfaceTest {
        
        /**
         * 定义了接口的static方法
         */
        public static void test() {
            System.out.println("这是接口的静态方法!");
        }
    }
    
    
    public class Test {    
        public static void main(Sting[] args) {
            //直接通过 接口名.方法名() 直接调用
            InterfaceTest.test();
        }
    }
    

    得到的结果是:

    这是接口的静态方法