java中不太常见的东西(3)
来源:互联网 发布:小甲鱼java 编辑:程序博客网 时间:2024/06/08 19:36
引言
上一篇博文我们主要介绍了关于Lambda表达式相关的知识,所以在今天的博文中我想把一个同样还不普及的类介绍给大家,Optional这个类是在Jdk1.8的时候引入的,它的主要功能是判断一个值是否为空,伴随着对数据相应的处理。笔者目前整理的一些blog针对面试都是超高频出现的。大家可以点击链接:http://blog.csdn.net/u012403290
技术点
1、静态工厂
我们在创建一个对象实例的时候,基本上都是靠构造器进行创建的。其实它还有一个更普及,但是你可能没发现的方法。它就是静态工厂方法, 它在类中是以一个静态方法的形态存在,比如说Intger类中有这么一段源码:
public static Integer valueOf(int i) {//一个静态工厂方法 if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
从上面的方法中,我们就可以直接返回一个Integer的实例。这种静态工厂方法相对于一般构造器来说有着诸多的优点,这里不一一展开,有兴趣可以参考《effective java》中的第一条。
O**ptional源码解读**
1、类介绍
public final class Optional<T> {}
从类定义上来看,我们可以看出亮点:a、它是一个不可扩展类,和String一样,是用final 修饰的,不能被继承,方法也不能被修改,因为final类中的方法都是默认final的;b、是一个泛型类,这个也是合理的,因为前面说过Optional的核心功能是对数据进行判断,因为对数据的未知,所以泛型的设计显得非常必要。
2、实例创建
以下是Optional的两个构造函数:
/** * Constructs an empty instance. * * @implNote Generally only one empty instance, {@link Optional#EMPTY}, * should exist per VM. */ private Optional() {//私有的不带参的构造函数 this.value = null; } /** * Constructs an instance with the value present. * * @param value the non-null value to be present * @throws NullPointerException if value is null */ private Optional(T value) {//私有的带参构造函数 this.value = Objects.requireNonNull(value); }
构造函数被定义成private的,说明这个类是不能通过构造函数进行实例化的。但是发现它具有几个可以创建实例等静态工厂方法:
//1 public static<T> Optional<T> empty() {//empty方法,可以反悔一个空的Optional对象 @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; }//2 public static <T> Optional<T> of(T value) {//of方法,可以传入一个value值,并返回一个带有value值的Optional对象 return new Optional<>(value); }//3 public static <T> Optional<T> ofNullable(T value) {//ofNullable方法,如果传入为空就返回一个空的Optional对象,如果传入值不为空就返回一个带有value的Optional对象 return value == null ? empty() : of(value); }
所以Optional对象不可以通过构造器的方式进行实例化,可以通过静态工厂方法创建一个对应的Optional实例。
3、关键方法
a、get
/** * If a value is present in this {@code Optional}, returns the value, * otherwise throws {@code NoSuchElementException}. * * @return the non-null value held by this {@code Optional} * @throws NoSuchElementException if there is no value present * * @see Optional#isPresent() */ public T get() {//获取Optional的值 if (value == null) {//如果值为null抛出一个错误 throw new NoSuchElementException("No value present"); } return value; }
get方法主要就是如果Optional中如果存在值就返回,为null就抛出一个错误。
b、isPresent
* Return {@code true} if there is a value present, otherwise {@code false}. * * @return {@code true} if there is a value present, otherwise {@code false} */ public boolean isPresent() { return value != null;//如果值存在返回true,否则返回false }
是一个boolean的方法,它主要是判Optional中的值是否存在,如果存在就返回true,如果不存在就返回false。
c、ifPresent
/** * If a value is present, invoke the specified consumer with the value, * otherwise do nothing. * * @param consumer block to be executed if a value is present * @throws NullPointerException if value is present and {@code consumer} is * null */ public void ifPresent(Consumer<? super T> consumer) { if (value != null)//如果值是否存在 consumer.accept(value);//值存在就需要调用consumer进行处理 }
关于consumer在昨天的Lambda表达式中我们就介绍过了,它是一个没有返回的函数接口。具体的我们在下面的例子中可以见到。
d、orElse
/** * Return the value if present, otherwise return {@code other}. * * @param other the value to be returned if there is no value present, may * be null * @return the value, if present, otherwise {@code other} */ public T orElse(T other) { return value != null ? value : other;//如果值存在则返回这个值,如果值不存在就返回输入 }
这个方法带有一个类型是输入,如果Optional的值不为空,则返回这个值,如果为空那么就返回输入。
e、filter
/** * If a value is present, and the value matches the given predicate, * return an {@code Optional} describing the value, otherwise return an * empty {@code Optional}. * * @param predicate a predicate to apply to the value, if present * @return an {@code Optional} describing the value of this {@code Optional} * if a value is present and the value matches the given predicate, * otherwise an empty {@code Optional} * @throws NullPointerException if the predicate is null */ public Optional<T> filter(Predicate<? super T> predicate) { Objects.requireNonNull(predicate); if (!isPresent()) return this; else return predicate.test(value) ? this : empty();//进行一次判断处理并返回 }
predicate在上一篇博文中也介绍过了,它是一个boolean的参数接口,可以进行条件判断。具体在demo中会掩饰。
f、map
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));//用function对value值进行修改 } }
Function的函数接口在上一篇博文中也介绍过了,它主要是传入一个类型的数据,返回一个类型的数据。在上面的源码种可以看出,返回的类型也是一个Optional的数据。
其实它还有几个方法和Object的方法,因为在上一片博文中没有设计过的东西,这里就不再展开。
一个完整的例子
以下是我写的详细demo:
package com.bw;import java.util.NoSuchElementException;import java.util.Optional;public class OptionalTest { public static void main(String[] args) { /** * 3种静态工厂生产Optional对象 */ //创建一个值为brickworker的Optional对象 Optional<String> o1 = Optional.of("brickworker"); //创建一个空的Optional Optional<String> o2 = Optional.empty(); //创建一个空的Optional Optional<String> o3 = Optional.ofNullable(null); //创建一个值为brickworker的Optional对象 Optional<String> o4 = Optional.ofNullable("brickworker"); //get方法 System.out.println("=========get方法=========="); System.out.println("o1存在值"+o1.get()); try { System.out.println("o2存在值"+o2.get());//o2和o3是空,会抛出错误,专门处理 } catch (Exception e) {//不必打印错误 } try { System.out.println("o3存在值"+o3.get());//o2和o3是空,会抛出错误,专门处理 } catch (Exception e) {//不必打印错误 System.out.println("o4存在值"+o4.get()); } System.out.println("========isPresent方法========="); if(o1.isPresent()){ System.out.println("o1有数据"); } if(o2.isPresent()){ System.out.println("o2有数据"); } if(o3.isPresent()){ System.out.println("o3有数据"); } if(o4.isPresent()){ System.out.println("o4有数据"); } System.out.println("===========orElse方法==========="); System.out.println(o1.orElse("o1没值输出这个")); System.out.println(o2.orElse("o2没值输出这个")); System.out.println(o3.orElse("o3没值输出这个")); System.out.println(o4.orElse("o4没值输出这个")); System.out.println("========map方法================="); Optional<String> no1 = o1.map(v -> v.toUpperCase()); System.out.println(no1.orElse("new o1如果没值输出这个")); Optional<String> no2 = o2.map(v -> v.toUpperCase()); System.out.println(no2.orElse("new o2如果没值输出这个")); Optional<String> no3 = o3.map(v -> v.toUpperCase()); System.out.println(no3.orElse("new o3如果没值输出这个")); Optional<String> no4 = o4.map(v -> v.toUpperCase()); System.out.println(no4.orElse("new o4如果没值输出这个")); System.out.println("============filter方法=============="); Optional<String> nno1 = o1.filter(v -> v.indexOf("brick") > -1);//如果字符串中存在brick System.out.println(nno1.orElse("nnew o1如果没值输出这个")); Optional<String> nno2 = o2.filter(v -> v.indexOf("brick") > -1);//如果字符串中存在brick System.out.println(nno2.orElse("nnew o1如果没值输出这个")); Optional<String> nno3 = o3.filter(v -> v.indexOf("brick") > -1);//如果字符串中存在brick System.out.println(nno3.orElse("nnew o1如果没值输出这个")); Optional<String> nno4 = o4.filter(v -> v.indexOf("brick") > -1);//如果字符串中存在brick System.out.println(nno4.orElse("nnew o1如果没值输出这个")); System.out.println("==========ifPresent方法=========="); o1.ifPresent(v -> {System.out.println("o1:"+v);}); o2.ifPresent(v -> {System.out.println("o2:"+v);}); o3.ifPresent(v -> {System.out.println("o3:"+v);}); o4.ifPresent(v -> {System.out.println("o4:"+v);}); }}//输出://=========get方法==========//o1存在值brickworker//o4存在值brickworker//========isPresent方法=========//o1有数据//o4有数据//===========orElse方法===========//brickworker//o2没值输出这个//o3没值输出这个//brickworker//========map方法=================//BRICKWORKER//new o2如果没值输出这个//new o3如果没值输出这个//BRICKWORKER//============filter方法==============//brickworker//nnew o1如果没值输出这个//nnew o1如果没值输出这个//brickworker//==========ifPresent方法==========//o1:brickworker//o4:brickworker
关于Optional类就介绍到这里,如果对于中间出现的Lambda表达式如果有不清楚的,请参考我上一篇博文。
以后大家在对输入值进行判断的时候,就可以用Optional来进行控制,从而防止NPE问题的产生。希望这篇博文对大家所有帮助,如果存在错误请帮忙指出。
- java中不太常见的东西(3)
- java中不太常见的东西(1)
- java中不太常见的东西(2)
- java中不太常见的东西(4)
- java中不太常见的东西(5)
- 常见的东西
- java 有用的东西
- java的一些东西
- java的东西,侵删
- Java 基础的东西
- .net 入门一些常见的东西
- c++一些不常见的东西
- java要学的东西
- java要学的东西
- Java swing 做的东西
- java一些基础的东西
- Java继承的一些东西
- java零碎东西的实例
- es6箭头函数
- Hadoop安装配置详解
- java多态
- 单例模式的七种写法
- 【Python】用C语言编写Python模块
- java中不太常见的东西(3)
- BootStrap(三) -- 通过tableExport实现数据导出
- ADG732: 32通道、串行控制、3.5 Ω、1.8 V至5.5 V/±2.5 V、模拟多路复用器
- TCP拥塞控制
- Unity手游UGUI开发之背包界面(MVC)
- 密电码
- 格式化秒,秒转换为: 时 分 秒的格式
- 电商行业
- endianness