JDK1.8 新特性 :方法引用 & Optional

117 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

1.方法引用

是lambda表达式的进一步简写,解决冗余,方法引用只能引用已经存在的方法。

1.1语法格式

符号标识 ::
符号说明: 双冒号为方法引用运算符,而他所在的表达式被称为方法引用
常见的场景:lambda 处理的逻辑或者方案已经存在或者实现,就可以使用方法引用(解决冗余)

1.2常见的引用方式

1.2.1. 对象名::方法名

测试:

public static void main(String[] args) {
    Date now = new Date();
    Supplier<Long> supplier=()->{
        return now.getTime();
    };
    System.out.println("supplier = " + supplier.get());
    //使用方法引用
    Supplier<Long> sup=now::getTime;
    System.out.println("sup = " + sup.get());

}

输出结果:

supplier = 1653903513893
sup = 1653903513893

1.2.2 类名:: 静态方法

测试:

public static void main(String[] args) {
    Supplier<Long> supplier=()->{
        return System.currentTimeMillis();
    };
    //通过方法引用
    System.out.println("supplier.get() = " + supplier.get());
    Supplier<Long> supplier1=System::currentTimeMillis;
    System.out.println("supplier1.get() = " + supplier1.get());


}

输出结果:

supplier.get() = 1653903741188
supplier1.get() = 1653903741217

System的静态方法currentTimeMillis()

public static native long currentTimeMillis();

1.2.3 类名:: 普通方法

测试:

public static void main(String[] args) {
    Function<String, Integer> supplier=(msg)->{
        return msg.length();
    };
    //通过方法引用
    Function<String, Integer> supplier2=String::length;
    BiFunction<String,Integer,String> su=String::substring;
    System.out.println("length= " + supplier.apply("supplier"));
    System.out.println("length= " + supplier2.apply("suppr"));
    System.out.println("su = " + su.apply("supplier",3));

}

输出结果:

length= 8
length= 5
su = plier

String的substring方法

public String substring(int beginIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    int subLen = value.length - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

1.2.4 类名 :: 类构造器

先准备一个对象
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserTest {

    private String name;

    private Integer age;
    
}

测试:

public static void main(String[] args) {
    Supplier<UserTest> supplier =()->{
        return new UserTest();
    };
    System.out.println("supplier = " + supplier.get());
    //方法引用
    Supplier<UserTest> supplier2=UserTest::new;
    System.out.println("supplier2 = " + supplier2.get());
    BiFunction<String,Integer,UserTest> biFunction=UserTest::new;
    System.out.println("biFunction = " + biFunction.apply("张三",12));

}

输出结果:

supplier = UserTest(name=null, age=null)
supplier2 = UserTest(name=null, age=null)
biFunction = UserTest(name=张三, age=12)

1.2.5 数组 :: 数组构造器

测试:

public static void main(String[] args) {
    Function<Integer,String[]> function =(msg)->{
        return new String[msg];
    };
    String[] apply = function.apply(8);
    System.out.println("function = " + apply.length);
    //方法引用的方式调用数组的构造器
    Function<Integer,String[]> function2=String[]::new;
    String[] apply1 = function2.apply(10);
    System.out.println("function2 = " + apply1.length);

}

输出结果:

function = 8
function2 = 10

方法引用是lambda 表达式符合特殊场景使用时的一种缩写,使得lambda表达时更加精简,减少代码的冗余。 方法引用只能引用已经存在的方法

2. Optional 类

Optional是用来解决空指针问题,正常开发中要做大量判断去避免。没有子类的,且可以为null的容器对象。

2.1 演示一个常见的错误

public static void main(String[] args) {
TestDTo testDTo = new TestDTo("张三",18,"33333@qq.com");
    TestDTo testDTo2=null;
    System.out.println("testDTo = " + testDTo.getEmail());
    System.out.println("testDTo2 = " + testDTo2.getEmail());

}

结果输出:

testDTo = 33333@qq.com
Exception in thread "main" java.lang.NullPointerException
	at com.asiaverify.api.sandbox.TestV.main(TestV.java:10)

2.2正常情况是需要做过滤的

public static void main(String[] args) {
TestDTo testDTo = new TestDTo("张三",18,"33333@qq.com");
    System.out.println("testDTo = " + testDTo.getEmail());
    TestDTo testDTo2=null;
    //需要排除这些null的情况
    if(testDTo2!=null){
        //去做自己的业务处理
        System.out.println("testDTo2 = " + testDTo2.getEmail());
    }else{
        System.out.println("testDTo2 = 为null");
    }
}

结果输出:

testDTo = 33333@qq.com
testDTo2 = 为null

2.3 Optional 的创建方式

 //返回空的 Optional 实例。
 static <T> Optional<T> empty()
 //返回一个指定非null值的Optional
 static <T> Optional<T> of(T value) 
 //如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional
 static <T> Optional<T> ofNullable(T value) 

测试:

public static void main(String[] args) {
    //empty
    Optional<Object> empty = Optional.empty();
    //of
    Optional<String> ceshi = Optional.of("ceshi");
   // Optional<String> ceshi2 = Optional.of(null);//不允许传入null 传入就会报空指针
    //ofnullable 这里传入null其实就是调用Optional.empty();
    Optional<String> ofnullableNull = Optional.ofNullable(null);
    System.out.println("ofnullableNull = " + ofnullableNull.isPresent());
    Optional<Integer> ofnullable = Optional.ofNullable(1);
    //这里使用了一下他的isPresent 是不是为空 包含返回 true 不包含返回false
    System.out.println("ofnullable = " + ofnullable.isPresent());
}

输出结果:

ofnullableNull = false
ofnullable = true

2.4 其他的常用方法

orElse

public static void main(String[] args) {
    //empty
    Optional<String> empty = Optional.empty();
    Optional<String> zhangsan = Optional.ofNullable("zhangsan");
    String xxx = zhangsan.orElse("xxx");
    System.out.println("zhangsan orElse= " + xxx);
    String xxx1 = empty.orElse("xxx");
    System.out.println("empty orElse = " + xxx1);

}

输出结果:

zhangsan orElse= zhangsan
empty orElse = xxx

orElse 对像有值时返回对像的值,没值时返回orElse(T t) 传入的t

//这是orElse方法
public T orElse(T other) {
    return value != null ? value : other;
}

orElseGet 方法如参数函数式接口

public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}

测试:

public static void main(String[] args) {
    //empty
    Optional<String> empty = Optional.empty();
    Optional<String> zhangsan = Optional.ofNullable("zhangsan");
    String s = zhangsan.orElseGet(() -> {
        return "xxxx";
    });
    System.out.println("zhangsan = " + s);

    String emptys = empty.orElseGet(() -> {
        //这里可以做一些特殊处理比起orElse方法来说
        return "xxxx";
    });
    System.out.println("empty = " + emptys);
}

输出结果:

zhangsan = zhangsan
empty = xxxx

orElseThrow

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

测试:

public static void main(String[] args) {
    //empty
    Optional<String> empty = Optional.empty();
    Optional<String> zhangsan = Optional.ofNullable("zhangsan");
    empty.orElseThrow(()->{
        //为null抛出这里返回的异常 不为空则返回 value
        return new RuntimeException();
    });
    zhangsan.orElseThrow(()->{
        return new RuntimeException();
    });
}
#### 实际场景演示
 将对象 TestDTo 不为 null 和 name 不为空是将name改为大写
```java
public static void main(String[] args) {

    //TestDTo testDTo =new TestDTo("",18,"2222@qq.com");
    TestDTo testDTo =new TestDTo("zhs",18,"2222@qq.com");

    Optional<TestDTo> empty = Optional.of(testDTo);
    empty.isPresent();
    String name = empty.map(TestDTo::getName).map(String::toUpperCase).orElse("name 为空");

    System.out.println("name = " + name);
}

结果输出:

name = ZHS

验证 name为空时

public static void main(String[] args) {

    TestDTo testDTo =new TestDTo(null,18,"2222@qq.com");

    Optional<TestDTo> empty = Optional.of(testDTo);
    empty.isPresent();
    String name = empty.map(TestDTo::getName).map(String::toUpperCase).orElse("name 为空");

    System.out.println("name = " + name);
}

结果输出:

name = name 为空

实践是检验真理的唯一方法! 明天见🥰🥰🥰