java接口及其新特性——Java基础回炉(三)

2018-11-19  本文已影响0人  TimeReview

前言

本文是Java基础回炉文集的第三篇,关于文集可通过《Java基础回炉和提升暨文集开篇》了解。

今天我们将从接口的基本概念出发,详细罗列了接口的基本语法特点,对比了接口和抽象类的异同点,并在此基础上总结了接口的意义以及应用实例,最后探讨了java8中对接口添加的新特性及其目的。


1. 定义

(1)什么是接口:

(2)接口的定义格式

//定义一个接口
interface 接口名{
    public static final String MSG = "hello";//全局常量
    public abstract void print();//抽象方法
}

(3)定义接口时应注意:

也就是说,对于接口,里面的组成只有抽象方法和全局常量,所以很多时候为了书写简单,可以不用写public abstract 或者public static final。并且,接口中的访问权限只有一种:public,即:定义接口方法和全局常量的时候就算没有写上public,那么最终的访问权限也是public

2. 接口的语法特点

3. 接口和抽象类的异同

3.1 语法层面异同

在《深入类和对象——深入Java基础系列(二)》中博主已经总结了抽象类的特点,下面将列表将接口和抽象类进行详细的对比。
(1)相同点:

(2)异同点:

接口和抽象类.png

3.2 设计层面异同

(1)抽象层次不同

例如,在Animal这个抽象类中,提取的动物eat()和sleep()的行为,那么子类Dog、Bird和Cat各自重写了两个方法,这里我们可以看到三者都是属于动物的。而我们知道并不是所有的动物都会飞,我们把飞的行为抽象为Ifly接口,这个飞的接口可以被Bird实现也可以被飞机实现,这里飞机和Bird之间没有什么关系。

也就是说,抽象类(父类)中定义的该对象的基本功能,而接口中定义的是该对象的扩展功能。

4. 接口的意义及应用实例

4.1 接口存在的意义

(1)重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的面向对象能力(封装、继承、多态)。接口是多态的一种实现方式。

(2)简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。

(3)维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类。

可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦。

如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。

(4)安全、严密性:接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。

4.2 应用实例

(1)原始代码:下面这段代码,来自阿里旗下虾米音乐产品代码,曾因为犀利注释而大火。

public class VIPCenter {
  void serviceVIP(T extend User user>) {
     if (user instanceof SlumDogVIP) {
        // 穷B VIP,活动抢的那种
        // do somthing
      } else if(user instanceof RealVIP) {
        // do somthing
      }
      // ...
  }

(2)缺陷:这段代码的一个问题是,业务逻辑集中在一起,当出现新的用户类型时,比如他们添加一个“金主VIP”,“爸爸VIP”,这就需要直接去修改服务方法代码实现,这可能会意外影响不相关的某个用户类型逻辑。
(3)改进方法:这时候可以把上述代码中通过条件判断语句判断用户类型而提供对应服务的方法进行抽象,把业务逻辑的紧耦合关系拆开,实现代码的隔离保证了方便的扩展。

   //一种类型的用户,对应自己的服务提供者类
   private Map<User.TYPE, ServiceProvider> providers;
   void serviceVIP(T extend User user) {
      //获取用户类型,并调用具体服务
      providers.get(user.getType()).service(user);
   }
 }
 //服务行为的抽象
 interface ServiceProvider{
   void service(T extend User user) ;
 }

 class SlumDogVIPServiceProvider implements ServiceProvider{
   void service(T extend User user){
     // do somthing
   }
 }
 class RealVIPServiceProvider implements ServiceProvider{
   void service(T extend User user) {
     // do something
   }
 }
//注释:上述应用实例借鉴《Java核心技术36讲》——杨晓峰

5. Java8中接口的新特性

(1)Java8新特性——接口的默认方法:简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。

public interface JDK8Interface {

    // static修饰符定义静态方法
    static void staticMethod() {
        System.out.println("接口中的静态方法");
    }

    // default修饰符定义默认方法
    default void defaultMethod() {
        System.out.println("接口中的默认方法");
    }
}

注意:静态方法,只能通过接口名调用,不可以通过实现类的类名或者实现类的对象调用。default方法,只能通过接口实现类的对象来调用。

public class JDK8InterfaceImpl implements JDK8Interface {
    //实现接口后,因为默认方法不是抽象方法,所以可以不重写,但是如果开发需要,也可以重写
    //静态方法不能被重写
}

public class Main {
    public static void main(String[] args) {
        // static方法必须通过接口类调用
        JDK8Interface.staticMethod();

        //default方法必须通过实现类的对象调用
        new JDK8InterfaceImpl().defaultMethod();
    }

(2)为什么要有这个特性:
首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。

(3)带来的问题:由于类可以实现多个接口,也可以继承类,当接口或类中有相同函数签名的方法时,这个时候到底使用哪个类或接口的实现呢?
这里有三个规则可以进行判断:

interface IA {
    default void print() {
        System.out.println("default method of IA");
    }
}
class ClassA {
    public void print() {
        System.out.println("method of ClassA");
    }
}
//类B继承了类A,且实现了接口A,且接口A的默认方法名和类A的方法名一样
class ClassB extends ClassA implements IA {

}

public class DefaultMethodTest {
    @Test
    public void test(){
        ClassB classB=new ClassB();
        classB.print();
    }
}
//  output:method of ClassA
// 解析:类中的方法优先级最高
interface IA {
    default void print() {
        System.out.println("default method of IA");
    }
}
interface IB extends IA{
    default void print() {
        System.out.println("default method of IB");
    }
}
//类A实现了接口A,接口B,接口B继承了接口A,且接口A和接口B有相同的方法
class ClassA implements IA,IB{

}
public class DefaultMethodTest {
    @Test
    public void test(){
        ClassA classA=new ClassA();
        classA.print();
    }
}
//output:default method of IB
//解析:B接口继承了A接口,那么B就比A更加具体
interface IA {
    default void print() {
        System.out.println("default method of IA");
    }
}
interface IB {
    default void print() {
        System.out.println("default method of IB");
    }
}
class ClassA implements IA, IB {
    @Override
    public void print() {
        IA.super.print();//显示调用期望的方法或者覆盖默认方法
    }
}
//output:default method of IA
//这里我有个疑问IA.super代表的什么意思

6. 总结

本文是Java基础回炉文件的第三篇,这篇文章主要介绍了java接口的基本特性,接口和抽象类的异同点,以及java8中接口的新特性。读完这篇文章的收获应该是:

上一篇下一篇

猜你喜欢

热点阅读