Java 8可选,而不是如果

问题描述:

我有可选的问题,我不知道如何处理它。Java 8可选,而不是如果

public void check(String name) { 
    if (name != null) 
     doSomething(name); 
    else 
     doMore(); 
} 

如果到可选如何改变呢?

+13

你不! '可选'不应该被传入方法中,它们仅用于返回可选值。你的代码是完美的,因为它现在是可能的(可能想添加一个'@ Nullable'注释) – luk2302

+1

在这种情况下,你真的不能,但是如果你的其他东西是'doSomething(“”);'那么'可选 name'可以像'doSomething(name.orElse(“”))一样使用;' –

+0

在这种情况下利用方法重载可能会更好,所以不带参数的check()方法会调用doMore()带有@NonNull String名称的check()方法只接受非空字符串。否则,请遵循Eugene或luk2302的建议。 – srborlongan

有应该是一个非常整洁的方法,但目前在JDK-9 ...

public void check(String name){ 
    Optional.ofNullable(name) 
      .ifPresentOrElse(YourClass::doSomething, YourClass::doMore); 
} 

假设doSomethingdoMore是静态的方法...如果没有实例应该使用,如this::doSomethingthis::doMore

+0

我认为它应该是'this :: doSomething'和'this :: doMore' – danielspaniol

+10

我会说这与* neat *非常相似。该代码比原始代码更长,更隐蔽。虽然技术上正确,但我会要求在Code Review中查看时更改它。 – luk2302

+0

@danielspaniol万一这些方法不是静态的 - 是的... – Eugene

虽然肯定是一个方法来创建使用Optional S也是一样的代码(例如见尤金的答案),你不应该在这里(恕我直言)使用Optional秒。

要么你会得到Optional传递给你的方法,这会给调用者带来开销,并且没有真正理解为什么/为什么使用Optional引入。
或者您可以自己在方法中创建Optional。这更“好”,但非常麻烦,模糊了实际发生的事情,如果在代码审查过程中遇到它,我会要求更改它。只需使用Optional和您当前的代码来比较片段 - 您的代码在字符方面可能较短,但很明显发生了什么。这里使用Optionals的唯一好处是,它似乎成为一个单线程,首先没有什么比可读性更重要,而且无论如何,如果您要添加一些大括号,则无需它就可以实现。


底线:你的代码是完全正常的,因为它是。

+1

这是非常有争议的......拒绝@Eugene的代码,即在评论中没有有效的技术论据。这只是一个品味问题,两种方式都可以。 *你*说功能的方式是不太可读的,但这可能完全是因为*你*是如此习惯于命令式的构造,它看起来很奇怪或不那么表达。一旦你习惯了功能结构*,这两种方法都是正确和清晰的。另一方面,没有理由用一些清晰可读的功能等价结构来替换一个清晰可读的命令式结构...... –

没有理由改变你的实现。有没有办法做你想要的东西在java 8与可选没有一个if,同时尊重不使用'地图'的副作用的想法。

我的意思是,你可以有

public void check(String name) { 
    Optional<String> nameOpt = Optional.ofNullable(name); 
    nameOpt.ifPresent(n -> doSomething(n)); 
    if (!nameOpt.isPresent()) { 
     doMore(); 
    } 
} 

,但有没有意义。 here你有一篇好文章,可选试图解决的问题(以及为什么要使用它):主要用于返回类型。其他的东西只是过度使用它。

您可以通过利用Java 8 Optional.map()Optional.orElseGet()方法避免if声明。检查下面的例子:

import java.util.Optional; 
import java.util.function.Consumer; 

final class OptionalTestMain { 

    public static void main(String[] args) { 
     check("test", str -> { 
      System.out.println("Yay, string is not null!"); 
      System.out.println("It's: " + str); 
     },() -> { 
      System.out.println("Crap, string is a null..."); 
      System.out.println("There is nothing for me to do."); 
     }); 

     check(null, str -> { 
      System.out.println("Yay, string is not null!"); 
      System.out.println("It's: " + str); 
     },() -> { 
      System.out.println("Crap, string is a null..."); 
      System.out.println("There is nothing for me to do."); 
     }); 
    } 

    static void check(String str, Consumer<String> ifPresent, Runnable ifNotPresent) { 
     Optional.ofNullable(str) 
       .map(s -> { ifPresent.accept(s); return s; }) 
       .orElseGet(() -> { ifNotPresent.run(); return null; }); 
    } 
} 

它会产生以下输出:

Yay, string is not null! 
It's: test 
Crap, string is a null... 
There is nothing for me to do. 

方法check预计3个参数:

  • 一个字符串(它可以是null
  • 一个Consumer拉姆达表达式用这个值做一些事情,不会改变的输入值。
  • a Runnable没有参数的lambda在输入时做某事Stringnull

当然,你可以很容易地修改下面的方法,然后利用Optional类的全部潜力,如:

static String checkAndReturn(String str, Function<String, String> ifPresent, Supplier<String> ifNotPresent) { 
    return Optional.ofNullable(str) 
      .map(ifPresent) 
      .orElseGet(ifNotPresent); 
} 

然后:

System.out.println(checkAndReturn("test", String::toUpperCase,() -> "no value")); 
System.out.println(checkAndReturn(null, String::toUpperCase,() -> "no value")); 

会产生以下的输出:

TEST 
no value 

我希望它有帮助。