Lambda 表达式
它是一个匿名函数,Java允许把函数作为参数传递进方法中。
语法格式:
1
| (parameters) -> expression 或是 (parameters) -> {statements;}
|
例如:
不采用lambda
1 2 3 4 5 6
| Runnable runnable1 = new Runable(){ @Override public void run(){ System.out.println("running without Lambda"); } }
|
使用lambda
1
| Runnable runnable2 =()->System.out.println("running from lambda")
|
相比于原来通过内部类传递参数,现在将函数作为参数直接传递到方法中使代码更加简洁紧凑
stream
java新增了串行流,不存储数据,但是它可以检索和逻辑处理集合数据,包括筛选、排序、统计、计数等
常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Test public void test() { List<String> strings = Arrays.asList("abc", "def", "gkh", "abc"); Stream<String> stringStream = strings.stream().filter(s -> "abc".equals(s)); long count = stringStream.count();
strings.stream().forEach(System.out::println);
Stream<String> limit = strings.stream().limit(1); String[] array = limit.toArray(String[]::new);
Stream<String> map = strings.stream().map(s -> s + "22");
strings.stream().sorted().forEach(System.out::println); }
|
Interface
interface 的设计初衷是面向抽象,提高扩展性。这也留有一点遗憾,Interface 修改的时候,实现它的类也必须跟着改。
为了解决接口的修改与现有的实现不兼容的问题。新 interface 的方法可以用default
或 static
修饰,这样就可以有方法体,实现类也不必重写此方法。
一个 interface 中可以有多个方法被它们修饰,这 2 个修饰符的区别主要也是普通方法和静态方法的区别。
default
修饰的方法,是普通实例方法,可以用this
调用,可以被子类继承、重写。
static
修饰的方法,使用上和一般类静态方法一样。但它不能被子类继承,只能用Interface
调用。
看实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public interface InterfaceNew { static void sm() { System.out.println("interface提供的方式实现"); } static void sm2() { System.out.println("interface提供的方式实现"); }
default void def() { System.out.println("interface default方法"); } default void def2() { System.out.println("interface default2方法"); } void f(); }
public interface InterfaceNew1 { default void def() { System.out.println("InterfaceNew1 default方法"); } }
|
如果有一个类既实现了 InterfaceNew
接口又实现了 InterfaceNew1
接口,它们都有def()
,并且 InterfaceNew
接口和 InterfaceNew1
接口没有继承关系的话,这时就必须重写def()
。不然的话,编译的时候就会报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class InterfaceNewImpl implements InterfaceNew , InterfaceNew1{ public static void main(String[] args) { InterfaceNewImpl interfaceNew = new InterfaceNewImpl(); interfaceNew.def(); }
@Override public void def() { InterfaceNew1.super.def(); }
@Override public void f() { } }
|
在 Java 8 ,接口和抽象类有什么区别的?
很多小伙伴认为:“既然 interface 也可以有自己的方法实现,似乎和 abstract class 没多大区别了。”
其实它们还是有区别的
- interface 和 class 的区别,好像是废话,主要有:
- 接口多实现,类单继承
- 接口的方法是 public abstract 修饰,变量是 public static final 修饰。 abstract class 可以用其他修饰符
- interface 的方法是更像是一个扩展插件。而 abstract class 的方法是要继承的。
开始我们也提到,interface 新增default
和static
修饰的方法,为了解决接口的修改与现有的实现不兼容的问题,并不是为了要替代abstract class
。在使用上,该用 abstract class 的地方还是要用 abstract class,不要因为 interface 的新特性而将之替换。
Optional
在阿里巴巴开发手册关于 Optional 的介绍open in new window中这样写到:
防止 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
。
1 2 3 4 5 6 7
| class Zoo { private Dog dog; }
class Dog { private int age; }
|
传统解决 NPE 的办法如下:
1 2 3 4 5 6 7 8
| Zoo zoo = getZoo(); if(zoo != null){ Dog dog = zoo.getDog(); if(dog != null){ int age = dog.getAge(); System.out.println(age); } }
|
层层判断对象非空,有人说这种方式很丑陋不优雅,我并不这么认为。反而觉得很整洁,易读,易懂。你们觉得呢?
Optional
是这样的实现的:
1 2 3
| Optional.ofNullable(zoo).map(o -> o.getDog()).map(d -> d.getAge()).ifPresent(age -> System.out.println(age) );
|
如何创建一个 Optional
上例中Optional.ofNullable
是其中一种创建 Optional 的方式。我们先看一下它的含义和其他创建 Optional 的源码方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
private static final Optional<?> EMPTY = new Optional<>();
private final T value;
public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
public static<T> Optional<T> empty() { Optional<T> t = (Optional<T>) EMPTY; return t; }
public static <T> Optional<T> of(T value) { return new Optional<>(value); }
private Optional(T value) { this.value = Objects.requireNonNull(value); }
public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; }
|
ofNullable
方法和of
方法唯一区别就是当 value 为 null 时,ofNullable
返回的是EMPTY
,of 会抛出 NullPointerException
异常。如果需要把 NullPointerException
暴漏出来就用 of
,否则就用 ofNullable
。