核心技术:接口、lambda表达式与内部类

来自Wikioe
Eijux讨论 | 贡献2020年10月17日 (六) 03:28的版本 →‎接口
跳到导航 跳到搜索


接口

接口(interface),是对类的一组需求描述(一组行为定义):

  1. 接口的所有方法自动属于public(不用提供public关键字);
  2. 接口中可以有常量,但是不能有实例域;
    即,域自动设置为:“public static final”
  3. 接口中可以有实现方法(Java SE 8 之后),但方法中不能引用实例域;
    默认:“public abstract”

提供实例域和方法实现,应该由实现接口的类来完成。

实现接口:

  1. 声明实现给定的接口:
    class Employee implements Comparable
    
  2. 对接口中的所有方法进行定义;
  • 所有方法都必须有实现;
  • 实现方法时,必须把方法声明为“public”;

接口的特性

  1. 接口不是类,不能用“new”进行实例化;
  2. 可以用接口声明变量,变量只能引用接口实现类的对象;
  3. 可以使用“instanceof”检查一个对象是否实现了某个特定接口(类似于检查对象是否属于某个类);
  4. 接口可以被继承,用新的接口扩展旧接口;

接口与抽象类

Java不支持多重继承(multiple inheritance):引入抽象类,避免多重继承的复杂性和低效性。

静态方法

Java 8 之后,允许接口中增加静态方法:

  • 静态方法无法实现多态,形式上重写,实际上是新方法。

默认方法

可以为接口方法提供一个默认实现(也可以不实现),并用“default”修饰该方法:

  1. 可以不用实现接口所有方法,只关注于需要的某个或某几个方法(可以不再使用伴随类):
    public interface MouseListener
    {
    	default void mousedieked(MouseEvent event) {}
    	default void mousePressed(MouseEvent event) {}
    	default void mouseReleased(MouseEvent event) {}
    	default void mouseEntered(MouseEvent event) {}
    	default void mouseExited(MouseEvent event) {}
    }
    
  2. 在为旧接口增加方法时,使用默认方法可以保证“源代码兼容”(source compatible);
    (增加非默认方法,会导致接口现有实现类不能正常工作)


关于伴随类

在JavaAPI 中,你会看到很多接口都有相应的伴随类,这个伴随类中实现了相应接口的部分或所有方法, 如 Collection/AbstractCollection 或 MouseListener/MouseAdapter。在JavaSE 8 中,这个技术已经过时。现在可以直接在接口中实现方法。

使用抽象类(伴随类)对接口进行部分实现,而后用户类并不之间实现接口(需要实现全部方法),而是继承与该抽象类(只重写需要的类即可)。如:

  1. public interface Collection<E> extends Iterable<E> {
    
    public abstract class AbstractCollection<E> implements Collection<E> {
    
  2. public interface MouseListener extends EventListener {
    
    public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener {
    
  3. 又见,SpringMVC 中的拦截器(见[1]):
    public interface HandlerInterceptor {
    
    public interface AsyncHandlerInterceptor extends HandlerInterceptor {
    
    public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
    

解决默认方法冲突

冲突:现在接口中将一个方法定义为默认方法,又在超类或另一个接口中定义了同样的方法;
规则:

  1. 超类优先:接口中的方法(不论是否默认方法)会被忽略;
  2. 接口冲突:一个接口提供默认方法,一个接口提供同名同参数方法(不论是否默认方法),则在实现类必须覆盖这个方法;

lambda

内部类

代理