接口和抽象类
抽象类
- 抽象类主要指不能具体实例化的类并且使用abstract关键字修饰,也就是说抽象类不能创建对象。
抽象方法
- 抽象方法主要指不能具体实现的方法并且使用abstract关键字修饰,也就是说抽象方法没有方法体。
注意事项
- 抽象类可以不包含抽象方法
- 含有抽象方法的类一定是抽象类
- abstract不能与static(用类名.的方式调用一个没有方法体的方法没有意义)、final(abstract子类需要重写,故矛盾)、private(不能继承,矛盾)共存
抽象类的实际意义
- 当一个类继承抽象类后必须重写抽象方法,否则该类也变成抽象类,也就是说抽象类对子类具有强制性和规范性,因此叫做模板设计模式。
接口
- 接口定义了某一批类所需要遵守的规范
- 接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法。
接口的语法规则
修饰符 interface 接口名 extends 父接口1, 父接口2... {
零个到多个常量定义...
零个到多个抽象方法的定义…
零个到多个默认方法的定义…(jdk1.8新增)
零个到多个静态方法方法的定义…(jdk1.8新增)
零个到多个私有方法的定义(jdk1.9新增)
零个到多个私有静态方法的定义(jdk1.9新增)
}
- 接口及接口成员的访问权限默认为:public
- 成员变量默认添加public static final关键字,即默认为常量。
- default、static、private修饰的方法可以添加方法体。
- default的目的是当接口中新增方法时,不用强行要求在所有子类中都重写一遍。
- static的目的是由于接口不能实例化对象,所以用于在没有必要创建对象的情况下,通过类名.的方式调用接口中的某些方法。
- private的目的是:对于接口中某些方法中重复的代码功能,进行提取封装成一个公共的方法,减少代码冗余时,此时这个公共的方法只用于接口内部,无需被子类访问及实现
- 总的来说接口中增加这些新特性的原因是,使得方法在接口的实现类中可以直接使用,以保障在扩展系统功能的同时,不对现有的继承关系及类库产生很大的影响,提高代码的可重用性
- 当一个类同时实现多接口,且其中同时具有相同方法时,实现类需重写该方法,否则会报编译错误
关于接口应用的常见问题
-
当父类实现接口,子类继承父类后,是否也要实现接口里的全部方法呢?
-
如果父类未实现接口中的全部方法,则父类需要设置为抽象类,子类如不想继续抽象,则需要实现相关未实现的方法,否则将继续作为抽象类。
-
如果父类已经实现了接口中所有方法,子类如无特殊需要,无需重新实现接口中方法。
-
-
关于接口引用指向接口实现类的问题
-
接口不能直接实例化对象,只能设置接口的引用指向具体的接口实现类。接口的灵活性就在于规定一个类必须做什么,而不管你如何做。所以我们定义一个接口类型的引用来指向接口实现类,然后当这个引用调用方法时,它会根据实际引用的类的实例来判断具体调用哪个方法,这是一种典型的多态的表现。
-
当使用接口引用指向实现类时,不能直接调用实现类独有的方法,需要进行强制类型转换之后才可以调用。
-
-
一个Java文件里可以存在几个接口?
- 在一个Java文件中可以存在多个类,多个接口,但是只能存在一个public修饰的类或接口,且此时文件名需要与public修饰的类或者接口同名。
-
如果继承的父类和实现的接口中存在相同定义的成员,且子类中无重新实现时,如何判断调用的是哪个?
-
无法判断将调用哪个常量
-
优先继承父类的成员方法及静态方法
-
抽象类和接口的主要区别
- 继承抽象类只支持单继承,而实现接口支持多实现。
- 抽象类中可以有构造方法,而接口中不可以有构造方法。
- 抽象类中可以有成员变量,而接口中只可以有常量。
- 抽象类中静态成员和方法可以被子类继承使用,而接口中的静态方法只属于接口
接口和抽象类的应用
实际应用中,抽象类通常用来捕捉子类的通用特性,即更加侧重重用;接口则多是为了把程序模块进行固化的契约,即侧重降低耦合。
接口可以理解为更加抽象的抽象类,但这并不意味着两者可以完全相互代替,它们都有各自适用的场景。
例如:当我们更希望描述多种毫无关系的类之间的共同行为能力时,更推荐用接口。而当多类间可以形成可追溯的产生轨迹时,通过抽象类继承则是更推荐的方式。