前言
只有光头才能变强
前两天带女朋友去图书馆了,随手就给她来了一本《与孩子一起学编程》的书,于是今天就给女朋友讲解一下什么是Optional类。
至于她能不能看懂,那肯定是看不懂的。(学到变量/for循环的女人怎么能看懂呢)
不知道大家还记得上一篇《阿里巴巴 Java开发手册》读后感不,当时阅读到空指针异常(NPE)时,书上提到JDK 8有个Optional类供我们使用,该类可以尽可能地防止出现空指针异常(NPE)。
文本力求简单讲清每个知识点,希望大家看完能有所收获
一、基础铺垫
我们都知道JDK 8最重要的新特性是Lambda表达式,这个可以让我们简化非常多的代码编写,不知道大家会使用了没有。这里我简单跟大家来回顾一下~
1.1Lambda简化代码例子
下面就以几个例子来看看Lambda表达式是怎么简化我们代码的编写的。
首先我们来看看创建线程:
public static void main(String[] args) { // 用匿名内部类的方式来创建线程 new Thread(new Runnable() { @Override public void run() { System.out.println("公众号:Java3y---回复1进群交流"); } }); // 使用Lambda来创建线程 new Thread(() -> System.out.println("公众号:Java3y---回复1进群交流")); }
再来看看遍历Map集合:
public static void main(String[] args) { Map<String, String> hashMap = new HashMap<>(); hashMap.put("公众号", "Java3y"); hashMap.put("交流群", "回复1"); // 使用增强for的方式来遍历hashMap for (Map.Entry<String, String> entry : hashMap.entrySet()) { System.out.println(entry.getKey()+":"+entry.getValue()); } // 使用Lambda表达式的方式来遍历hashMap hashMap.forEach((s, s2) -> System.out.println(s + ":" + s2)); }
在List中删除某个元素
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Java3y"); list.add("3y"); list.add("光头"); list.add("帅哥"); // 传统的方式删除"光头"的元素 ListIterator<String> iterator = list.listIterator(); while (iterator.hasNext()) { if ("光头".equals(iterator.next())) { iterator.remove(); } } // Lambda方式删除"光头"的元素 list.removeIf(s -> "光头".equals(s)); // 使用Lambda遍历List集合 list.forEach(s -> System.out.println(s)); }
从上面的例子我们可以看出,Lambda表达式的确是可以帮我们简化代码的。
1.1函数式接口
使用Lambda表达式,其实都是建立在函数式接口上的。我们看看上面的代码的接口:
创建多线程的Runnable接口:
@FunctionalInterface public interface Runnable { public abstract void run(); }
遍历HashMap的BiConsumer接口:
@FunctionalInterface public interface BiConsumer<T, U> { void accept(T t, U u); default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) { Objects.requireNonNull(after); return (l, r) -> { accept(l, r); after.accept(l, r); }; } }
在List中删除元素的Predicate接口:
@FunctionalInterface public interface Predicate<T> { boolean test(T t); default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } default Predicate<T> negate() { return (t) -> !test(t); } default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }
函数式接口的特点:由@FunctionalInterface
注解标识,接口有且仅有一个抽象方法!
1.2Lambda简单讲解
或许我们一开始看到Lambda的时候,发现Lambda表达式的语法有点奇葩,甚至有点看不懂。没事,这里3y给大家用图的形式画一画:
Lambda表达式组成
以Runnable接口来举例:
Lambda表达式很简单!
再不济,我们在用IDE的时候,可以提示出Lambda表达式的语法的,这样可以帮我们快速上手Lambda表达式:
IDEA提示Lambda表达式
说白了,我们使用Lambda表达式的架子是这样的()->{}
,具体的时候看看函数式接口的抽象方法要求就可以了,再不济就使用IDE智能提示。
1.3泛型回顾
比如说public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
这个声明,你看懂了吗?
// 接口 @FunctionalInterface public interface Function<T, R> { R apply(T t); }
在泛型的上限和下限中有一个原则:PECS(Producer Extends Consumer Super)
带有子类限定的可以从泛型读取【也就是--->(? extend T)】-------->Producer Extends
带有超类限定的可以从泛型写入【也就是--->(? super T)】-------->Consumer Super
解析:传入的参数是泛型 T 或者其父类,返回值是U或其子类。
具体可参考:
二、Optional类
一句话介绍Optional类:使用JDK8的Optional类来防止NPE(空指针异常)问题。
接下来我们看看文档是怎么说的:
A container object which may or may not contain a non-null value.Additional methods that depend on the presence or absence of a contained value are provided
它是一个容器,装载着非NULL元素(或者没有装载元素),提供了一系列的方法供我们判断该容器里的对象是否存在(以及后续的操作)。
Optional类的方法结构图:
Optional类的方法结构图
2.1创建Optional容器
我们先来看看Optional的属性以及创建Optional容器的方法:
// 1、创建出一个Optional容器,容器里边并没有装载着对象 private static final Optional<?> EMPTY = new Optional<>(); // 2、代表着容器中的对象 private final T value; // 3、私有构造方法 private Optional() { this.value = null; } // 4、得到一个Optional容器,Optional没有装载着对象 public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } // 5、私有构造方法(带参数),参数就是具体的要装载的对象,如果传进来的对象为null,抛出异常 private Optional(T value) { this.value = Objects.requireNonNull(value); } // 5.1、如果传进来的对象为null,抛出异常 public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; } // 6、创建出Optional容器,并将对象(value)装载到Optional容器中。 // 传入的value如果为null,抛出异常(调用的是Optional(T value)方法) public static <T> Optional<T> of(T value) { return new Optional<>(value); } // 创建出Optional容器,并将对象(value)装载到Optional容器中。 // 传入的value可以为null,如果为null,返回一个没有装载对象的Optional对象 public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
作者:Java3y
链接:https://www.jianshu.com/p/9143028217b9
共同学习,写下你的评论
评论加载中...
作者其他优质文章