java8新特性

jdk8的发布时间是2014年,也是现在市面上用的最多的jdk版本,在这里记录一下它的新特性

1、接口中方法的实现

在java8中接口可以有默认的实现,default修饰的方法是普通的方法,可以通过this调用,如果一个类实现了两个接口,并且两个接口中有一个同名的default方法时,必须要重写此方法,不然会有编译异常,静态方法,静态方法跟一般类的静态方法一样,但是不能被继承,但是可以使用接口调用,这样在策略模式时,可以将公共类写到接口中,然后通过接口.静态方法进行公共方法的调用。

2、函数式接口

在一个接口中有且只有一个抽象方法,但可以有多个非抽象方法,就是函数式接口,可以通过@FunctionalInterface来标注检查

3、lambda表达式

lambda是java8中的一个重要的特性,让java也能够支持简单的函数式编程,它实际上是一个匿名内部类。

(parameters) -> expression 或
(parameters) ->{ statements; }

Runnable 接口

new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("The runable now is using!");
            }
}).start();
//用lambda
new Thread(() -> System.out.println("It's a lambda function!")).start();

Comparator 接口

List<Integer> strings = Arrays.asList(1, 2, 3);

Collections.sort(strings, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
    return o1 - o2;}
});

//Lambda
Collections.sort(strings, (Integer o1, Integer o2) -> o1 - o2);
//分解开
Comparator<Integer> comperator = (Integer o1, Integer o2) -> o1 - o2;
Collections.sort(strings, comperator);

4、自定义函数式接口及使用

@FunctionalInterface
public interface ComputeI {
    double compute(double x,double y);
}

 第一种使用方法,实现加法和减法

    ComputeI computePlus =
        (a, b) -> {
          return a + b;
        };

    double plus = computePlus.compute(3, 2);
    System.out.println(plus);
    ComputeI computeSubtract =
            (a, b) -> {
              return a - b;
            };
    double subtract = computeSubtract.compute(3, 2);
    System.out.println(subtract);

第二种使用方法

public class MainTest02 {
  public static void main(String[] args) {
    //加法运算
      compute(3,4, (x,y)->{
          return x+y;
      });
      //减法运算
      compute(6,4, (x,y)->{
          return x-y;
      });
  }

  public static void compute(int x,int y,ComputeI computeI){
      double compute = computeI.compute(x, y);
    System.out.println(compute);
  }
}

5、双冒号方法引用

Java 8 允许使用 :: 关键字来传递方法或者构造函数引用

方法引用分为三种,方法引用通过一对双冒号:: 来表示,方法引用是一种函数式接口的另一种书写方式

  • 静态方法引用,通过类名::静态方法名, 如 Integer::parseInt
  • 实例方法引用,通过实例对象::实例方法,如 str::substring
  • 构造方法引用,通过类名::new, 如 User::new
public static void main(String[] args) {  
    // 使用双冒号::来构造静态函数引用  
    Function<String, Integer> fun = Integer::parseInt;  
    Integer value = fun.apply("123");  
    System.out.println(value);  
  
    // 使用双冒号::来构造非静态函数引用  
    String content = "Hello JDK8";  
    Function<Integer, String> func = content::substring;  
    String result = func.apply(1);  
    System.out.println(result);  
  
    // 构造函数引用  
    BiFunction<String, Integer, User> biFunction = User::new;  
    User user = biFunction.apply("mengday", 28);  
    System.out.println(user.toString());  
  
    // 函数引用也是一种函数式接口,所以也可以将函数引用作为方法的参数  
    sayHello(String::toUpperCase, "hello");  
}  
  
// 方法有两个参数,一个是  
private static void sayHello(Function<String, String> func, String parameter){  
    String result = func.apply(parameter);  
    System.out.println(result);  
}

6、stream流

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

Stream可以由数组或集合创建,对流的操作分为两种:

中间操作,每次返回一个新的流,可以有多个。
终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。
另外,Stream有几个特性:

stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。

按执行类型分为stream顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,可多线程执行

7、Optional

防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:

1) 返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。

反例:public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。

2) 数据库的查询结果可能为 null。

3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。

4) 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。

5) 对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针。

6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。

正例:使用 JDK8 的 Optional 类来防止 NPE 问题。

假设有一个 Zoo 类,里面有个属性 Dog,需求要获取 Dog 的 age

class Zoo {
   private Dog dog;
}

class Dog {
   private int age;
}

传统解决 NPE 的办法如下:

Zoo zoo = getZoo();
if(zoo != null){
   Dog dog = zoo.getDog();
   if(dog != null){
      int age = dog.getAge();
      System.out.println(age);
   }
}

使用Optional实现,其中ofNullable和of的区别是,当person对象为null时,of会抛出nullpoint,而ofNullable返回的是Empty

    @Test
    public void test() {

        Person person =null;
        Optional.ofNullable(person).map(o -> o.getMen()).map(d -> d.getName()).ifPresent(age ->
                System.out.println(age)
        );
        Optional.of(person).map(o -> o.getMen()).map(d -> d.getName()).ifPresent(age ->
                System.out.println(age)
        );
    }

map()相关方法。

/**
* 如果value为null,返回EMPTY,否则返回Optional封装的参数值
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
}
/**
* 如果value为null,返回EMPTY,否则返回Optional封装的参数值,如果参数值返回null会抛 NullPointerException
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
}

2.flatMap() 参数返回值如果是 null 会抛 NullPointerException,而 map() 返回EMPTY

map和flatmap区别,比如有两组元素,map是对两组元素中的每个元素做对应处理,flatmap可以对元素处理并整合成一个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值