关于java:Java8中你可能不知道的一些地方之接口默认方法实战

2次阅读

共计 4570 个字符,预计需要花费 12 分钟才能阅读完成。

Java8 曾经公布很久,是自 java5(2004 年公布)之后 Oracle 公布的最重要的一个版本。其中包含语言、编译器、库、工具和 JVM 等诸多方面的新个性,对于国内外互联网公司来说,Java8 是当前技术开发的趋势。这里次要解说在开发中几个外围的新个性。(次要从新个性概念解释、语法定义、简略代码演示、优缺点剖析、我的项目实战几个方面编写)。

一、外围个性总览

二、接口默认办法

在注册网站时,咱们会在注册后应用网站提供的默认头像,利用程序安装胜利后通常会提供默认图标,在电商网站购买过商品进行领取时,咱们会设置罕用收货地址为默认地址,看起来生存中很多场景都有默认一说。Java8 开始,同样也有默认这个词的呈现,这里针对接口 Java8 扩大了接口原有性能,并对默认办法提供反对。

2.1 概念

从 Java8 开始,程序容许在接口中蕴含带有具体实现的办法,应用 default 润饰,这类办法就是默认办法。默认办法在接口中能够增加多个,并且 Java8 提供了很多对应的接口默认办法。

2.2 语法

Java8 中接口能够蕴含实现办法,须要应用 default 润饰,此类办法称为默认办法。默认办法在接口中必须提供实现,在实现类中能够按需重写。默认办法只能在实现类中或通过实现类对象调用。如下模式:

public interface IMathOperation {
   /**
    * 定义接口默认办法 反对办法形参
    */
   default void print(){System.out.println("数值运算根本接口默认打印办法。。。");
  }
}

2.3 简略应用

  • 接口定义

定义 IMathOperation 接口并提供默认打印办法

public interface IMathOperation {
   /**
    * 定义接口默认办法 反对办法形参
    */
   default void print(){System.out.println("这是数值运算根本接口。。。");
  }
   /**
    * 整数加法运算办法
    * @param a
    * @param b
    * @return
    */
   public int add(int a,int b);
}
  • 子类实现

定义 MathOperationImpl 子类实现 IMathOperation 接口

子类在实现时,按需重写接口默认办法

public class MathOperationImpl implements  IMathOperation {
   @Override
   public int add(int a, int b) {
       // 子类中能够间接调用父类接口默认办法
       IMathOperation.super.print();
       // 调用父类动态默认办法
       IMathOperation.version();
       return a+b;
  }
}

2.4 多个默认办法

应用 Java8 开发应用程序,子类实现多个接口时,对于接口默认办法定义容许定义多个默认办法,并且接口默认办法可能会呈现同名状况,此时对于子类在实现或者调用时通常遵循以下准则:

1. 类中的办法优先级最高

2. 如果第一条无奈进行判断,那么子接口的优先级更高:函数签名雷同时,优先选择领有最具体实现的默认办法的接口,即如果 B 继承了 A,那么 B 就比 A 更加具体

示例代码如下:

/**
* 定义手机接口 提供默认 info 办法
*/
public interface Phone {default void info(){System.out.println("这是一部手机");
  }
}

/**
* 定义 MiPhone 子接口 并继承 Phone 父接口 同时也提供 info 办法
*/
public interface MiPhone extends Phone{default void info(){System.out.println("这是一部小米手机");
  }
}

/**
* 实现 Phone MiPhone 接口
*/
public class M2sPhone implements Phone,MiPhone {public static void main(String[] args) {new M2sPhone().info();}
}

打印后果:
这是一部小米手机 

三、接口静态方法

接口中除了容许定义多个默认办法之外,Java8 也容许在接口中定义多个静态方法,静态方法即通过 static 润饰的办法。接口中静态方法也必须提供实现,提供了能够间接通过接口调用办法的形式。

public interface IMathOperation {
   /**
    * 定义接口默认办法 反对办法形参
    */
   default void print(){System.out.println("这是数值运算根本接口。。。");
  }
   
    /**
    * 定义动态默认办法
    */
   static void version(){System.out.println("这是 1.0 版繁难计算器");
  }    
}

接口中的静态方法只能通过接口自身去调用,相似于 Class 中的静态方法,不存在默认办法中的多继承问题,静态方法并不能在实现类中被覆写,实现类中能够申明雷同的办法,但这两个办法之间除了名字雷同,并没有 Override 关系。

四、接口默认办法实战

4.1 网站沉闷 TOP3 用户遍历

这里以博客网站举例,比方统计每个月网站前三沉闷用户 (按用户文章发表量评判),应用汇合遍历操作来应用接口默认办法,对于测试数据如下:

uList=  new ArrayList<>();
uList.add(new UserDto(35,"zs","126xxx@126.com",800,"lv4"));
uList.add(new UserDto(60,"js_li","157xxx@139.com",500,"lv3"));
uList.add(new UserDto(78,"fc_007","126@126.com",260,"lv2"));
  • 加强 for 实现

失去统计汇合数据后,最简略的形式应用加强 for 实现,也是 java8 之前罕用的形式。

System.out.println("---------- 汇合遍历 --> 原始遍历办法 ---------");
for(UserDto u:uList){System.out.println(u);
}
  • 自定义接口默认办法
/**
* @Version 1.0
* 定义 MyList 接口 并提供 myForeach 默认办法
*/
public interface MyList<T> {
   /**
    * 定义接口默认办法
    * @param t
    */
  default public  void myForeach(List<T> t){for(Object o:t){System.out.println(o);
      }
  }
}

/**
* @Version 1.0
* 定义 MyArrayList 子类 实现 MyList 接口, 继承 ArrayList
*/
public class MyArrayList<T> extends ArrayList<T> implements MyList<T> { }

/**
 执行遍历
*/
System.out.println("---------- 汇合遍历 --> 自定义接口默认办法 ---------");
// 应用自定义的接口默认办法实现汇合元素遍历
uList.myForeach(uList);
  • 应用加强的 Iterable 接口默认办法

System.out.println("---------- 汇合遍历 --> 加强的 List 接口默认办法 ---------");
uList.forEach(new Consumer<UserDto>() {
        @Override
        public void accept(UserDto userDto) {System.out.println(userDto);
        }
    });
}

4.2、网站沉闷 TOP3 用户排序

这里以博客网站举例,比方统计每个月网站前三沉闷用户 (按用户文章发表量评判),应用汇合排序操作来应用接口默认办法,对于测试数据如下:

  • Collections.sort 工具类办法实现排序
System.out.println("--------Collections.sort 实现按文章发表量排序 ---------");
       Collections.sort(uList, new Comparator<UserDto>() {
           @Override
           public int compare(UserDto o1, UserDto o2) {return o1.getTotal()-o2.getTotal();}
      });
uList.forEach(System.out::println);
  • 加强的 List 接口默认 sort 办法

借助 Java8 加强的 List 接口默认 Sort 办法实现汇合排序操作

System.out.println("-------- 汇合默认 sort 办法实现按文章发表量排序 ---------");
       uList.sort(new Comparator<UserDto>() {
           @Override
           public int compare(UserDto o1, UserDto o2) {return o1.getTotal()-o2.getTotal();}
      });
uList.forEach(System.out::println);
  • Stream 流 sorted 办法实现排序 (这里先做理解!)

Stream 流提供了针对汇合的多种操作,这里借助 Stream 的 sorted 实现汇合元素排序操作,后续会对 Stream 做具体介绍。

System.out.println("--------Stream 实现按文章发表量排序 ---------");
      List<UserDto> result= uList.stream().sorted(new Comparator<UserDto>() {
           @Override
           public int compare(UserDto o1, UserDto o2) {return o1.getTotal()-o2.getTotal();}
      }).collect(Collectors.toList());
result.forEach(System.out::println);

五、接口默认办法与静态方法的劣势

1、接口的兼容性失去解决

应用接口编程的益处是,开发是面向形象而不再是面向具体来编程,使得程序变得很灵便,缺点是,当须要批改接口时候,此时对应实现该接口的类须要全副批改,举个例子,java 8 之前对于咱们罕用的汇合框架没有 foreach 办法,通常能想到的解决办法是在 JDK 里给相干的接口增加新的办法及实现。从 Java8 开始,引入了接口默认办法,这样的益处也是很显著的,首先解决了 Java8 以前版本接口兼容性问题,同时对于咱们当前的程序开发,也能够在接口子类中间接应用接口默认办法,而不再须要再各个子类中各自实现响应接口办法。

2、子类在实现接口办法时灵便度更高

子类在实现接口时,能够按需重写,不再向 Java8 以前接口办法必须全副实现,同时接口默认办法能够在子类中间接进行调用,灵便度比拟高。

3、开发中防止大量工具类创立

接口中引入静态方法,对于原有我的项目开发中呈现大量的工具类大量静态方法的代码便能够迁徙到接口中定义与实现,省去大量工具类的创立。

4、晋升了对 Lambda 表达式的反对

Lambda 是针对只有一个形象办法的接口来说的,接口中引入接口默认办法与静态方法,在对接口这些办法进行调用时,能够引入 Lambda 表达式简化了原有代码的书写模式,使得代码变得更加简洁。

正文完
 0