zoukankan      html  css  js  c++  java
  • Java8新特性Optional、接口中的默认方法与静态方法

    Optional

    Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。

    常用方法:

    Optional.of(T t) : 创建一个 Optional 实例。

    Optional.empty() : 创建一个空的 Optional 实例。

    Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例。

    isPresent() : 判断是否包含值。

    orElse(T t) : 如果调用对象包含值,返回该值,否则返回t。

    orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值。

    map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()。

    flatMap(Function mapper):与 map 类似,要求返回值必须是Optional。

    下面引用ImportNew的一段内容来告诉我们如何正确使用Optional。比如千万不要写成这样子:

    public static String getName(User u) {
        Optional<User> user = Optional.ofNullable(u);
        if (!user.isPresent())
            return "Unknown";
        return user.get().name;
    }

    这样改写非但不简洁,而且其操作还是和第一段代码一样。无非就是用isPresent方法来替代u==null。这样的改写并不是Optional正确的用法,我们再来改写一次。

    public static String getName(User u) {
        return Optional.ofNullable(u)
                        .map(user->user.name)
                        .orElse("Unknown");
    }

    这样才是正确使用Optional的姿势。那么按照这种思路,我们可以安心的进行链式调用,而不是一层层判断了。看一段代码:

    public static String getChampionName(Competition comp) throws IllegalArgumentException {
        if (comp != null) {
            CompResult result = comp.getResult();
            if (result != null) {
                User champion = result.getChampion();
                if (champion != null) {
                    return champion.getName();
                }
            }
        }
        throw new IllegalArgumentException("The value of param comp isn't available.");
    }

    由于种种原因(比如:比赛还没有产生冠军、方法的非正常调用、某个方法的实现里埋藏的大礼包等等),我们并不能开心的一路comp.getResult().getChampion().getName()到底。而其他语言比如kotlin,就提供了在语法层面的操作符加持:comp?.getResult()?.getChampion()?.getName()。所以讲道理在Java里我们怎么办!

    让我们看看经过Optional加持过后,这些代码会变成什么样子。

    public static String getChampionName(Competition comp) throws IllegalArgumentException {
        return Optional.ofNullable(comp)
                .map(c->c.getResult())
                .map(r->r.getChampion())
                .map(u->u.getName())
                .orElseThrow(()->new IllegalArgumentException("The value of param comp isn't available."));
    }

    这就很舒服了。Optional的魅力还不止于此,Optional还有一些神奇的用法,比如Optional可以用来检验参数的合法性。

    public void setName(String name) throws IllegalArgumentException {
        this.name = Optional.ofNullable(name).filter(User::isNameValid)
                            .orElseThrow(()->new IllegalArgumentException("Invalid username."));
    }

    上面代码引用importnew—Java8 如何正确使用 Optional。

    接口中的默认方法与静态方法

    Java8接口中可以添加静态方法,也可以添加默认方法,默认方法用 default修饰。

    public interface Fun<T> {
    
        default void getName(){
            System.out.println("hello world");
        }
    
        static void getAge(){
            System.out.println("nine");
        }
    
    }

    若一个接口中定义了一个默认方法,他的实现类的一个父类定义了具有相同名称和参数列表的方法。则调用该实现类的时候执行父类中的方法。

    public class TestF {
        public void getName(){
            System.out.println("TestF");
        }
    }
    
    public interface TestInterface {
        default void getName(){
            System.out.println("hello world");
        }
    }
    
    public class Test extends TestF  implements TestInterface{
        public static void main(String[] args) {
            Test t = new Test();
            t.getName();//输出的是TestF
        }
    }

    若一个实现类实现了两个接口,如果一个父接口提供一个默认方法,而另一个父接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法来解决冲突,否则会报错。

    public interface TestInterface {
        default void getName(){
            System.err.println("hello world");
        }
    }
    public interface TestInterface1 {
         void getName();
    }
    public class Test1 implements TestInterface, TestInterface1{
        public void getName(){
            System.out.println("Tes1F");
        }
    }
    java学习群669823128
  • 相关阅读:
    hdu5834 Magic boy Bi Luo with his excited tree 【树形dp】
    POJ2152 Fire 【树形dp】
    POJ1848 Tree 【树形dp】
    hdu3586 Information Disturbing 【树形dp】
    BZOJ4557 [JLoi2016]侦察守卫 【树形dp】
    BZOJ4000 [TJOI2015]棋盘 【状压dp + 矩阵优化】
    BZOJ1487 [HNOI2009]无归岛 【仙人掌dp】
    BZOJ4002 [JLOI2015]有意义的字符串 【数学 + 矩乘】
    洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】
    3-3 银行业务队列简单模拟
  • 原文地址:https://www.cnblogs.com/rese-t/p/7977605.html
Copyright © 2011-2022 走看看