首页 > 图灵资讯 > 技术篇>正文

java8新特性之Optional类

2023-04-04 10:29:40

到目前为止,臭名昭著的空指针异常是由于Java应用程序失败的最常见原因。过去,为了解决空指针异常,Google著名的Guava项目引入了Optional。Guava鼓励程序员通过检查空值来防止代码污染。去谷歌 Guava的启发,java8的新特点Optional类已经成为Java 8类库的一部分,作为java8的新特性诞生了。

Optional 类(java.util.Optional) 是容器类,它是一个box类型,保持引用另一个对象。Optional类是不可变的,不可序列化的,它代表一个值存在或不存在,以前一直都是 null 表示一个值不存在,现在 Optional 能更好地表达这个概念。

Optional隐藏了空指针的不确定性,例如:

List numbers= ImmutableList.of("ONE", "TWO", "THREE");

return numbers.stream()

.filter(number -> "FOUR".equals(number))

.findAny()

.toLoweCase();

结果会导致使用ifllpointerexceptions空指针是错误的 判断else是一种切割器cutter

List numbers= ImmutableList.of("ONE", "TWO", "THREE");

String numberThatImLookingFour =

numbers.stream()

.filter(number -> "FOUR".equals(number))

.findAny();

if(numberThatImLookingFour != null){

return numberThatImLookingFour.toLowerCase();

}else{

return "not found";

}

我们的目的是为库方法的返回类型提供有限的机制,其中需要一种明确的方法来表示“无结果”,使用nulll绝对可能会导致错误。因此,添加了Optional ,这不是一个真正的新概念,历史可以追溯到Haskell的Maybel monad。突然间,我们得到了JDK批准表示可能存在或不存在的值,以前推出的java的新特性是一样的,在各地使用新功能的开发人员欣喜若狂

空引用空指针是无数错误的来源,通常无法很好地识别“不存在”这个概念。传入领域的所有变量都需要执行业务逻辑。我们必须减少if的编写(obj == null)检查判断的代码行数量。我们仍然需要与外部世界(数据库查询、REST端点等)交互,并根据执行逻辑进行交互输出。如果使用Optional 可以提供适当的帮助。

有一种诱惑是调用get()获取其中值。我们都知道普通Javabean的getter / setters :)。并且希望如果我们调用gett,我们会调用gett ...()我们会得到一些东西。调用普通bean的getter时,你永远不会得到任何异常抛出。但是,如果在optional上调用get方法,且选项内部为空,则抛出异常nosuchelementexception。

这些方法应该被称为getOrThorwSomeHorribleError()因此,第一条和第二条规则:

1、不要把nulll给Optionall

2、避免使用Optional.get()。假如你不能证明有可选项,那么永远不要调用get()。

使用orElse(), orElseGet(), orElseThrow().得到你的结果。我们可以重构以下代码:

String variable = fetchSomeVaraible();

if(variable == null){

1. throw new IllegalStateException("No such variable");

2. return createVariable();

3. return "new variable";

} else {

...

100 lines of code

...

}

重构到:

1.

Optional variableOpt = fetchOptionalSomeVaraible();

String variable = variableOpt.orElseThrow(() -> new Exeption(""))

... 100 lines of code ...

2.

Optional variableOpt = fetchOptionalSomeVaraible();

String variable = variableOpt.orElseGet(() -> createVariable())

... 100 lines of code ...

3.

Optional variableOpt = fetchOptionalSomeVaraible();

String variable = variableOpt.orElse("new variable")

... 100 lines of code ...

注意,orElse(..)急切计算意味着以下代码:

Optional optionalDog = fetchOptionalDog();

optionalDog

return "CAT";

}

}

重构到:

Optional dog = fetchDogIfExists();

String dogsName = dog

.map(this::convertToDog)

.orElseGet(this::convertToCat)

public void convertToDog(Dog dog){

return "DOG'd name is : " + dog.getName();

}

public void convertToCat(){

return "CAT";

}

Filter是一种有用的折叠语法:

Dog dog = fetchDog();

if(optionalDog != null && optionalDog.isBigDog()){

doBlaBlaBla(optionalDog);

}

上述代码可重构为:

Optional optionalDog = fetchOptionalDog();

optionalDog

.filter(Dog::isBigDog)

.ifPresent(this::doBlaBlaBla)

6、不要为了链法而使用optionall 。

使用optional 我们应该注意的一件事是链式方法的诱惑。当我们像构建器模式一样链接时,事物可能看起来很漂亮:)。但这并不总是意味着它更可读。所以不要这样做:

Optional

.ofNullable(someVariable)

.ifPresent(this::blablabla)

它不利于性能和可读性。我们应该尽可能多地这样做。避免使用null引用。

7、使所有表达式成为单行lambda

这是一个更常见的规则,我认为它也应用于流动。使用Optional 记住等式左侧和右侧一样重要:

Optional

.ofNullable(someVariable)

.map(variable -> {

try{

return someREpozitory.findById(variable.getIdOfOtherObject());

} catch (IOException e){

LOGGER.error(e);

throw new RuntimeException(e);

}})

.filter(variable -> {

if(variable.getsomeField1() != null){

return true;

} else if(variable.getsomeField2() != null){

return false;

} else {

return true;

}

})

.map((variable -> {

try{

return jsonMapper.toJson(variable);

} catch (IOException e){

LOGGER.error(e);

throw new RuntimeException(e);

}}))

.map(String::trim)

.orElseThrow(() -> new RuntimeException("something went horribly wrong."))

以上冗长代码块可以用方法代替:

Optional

.ofNullable(someVariable)

.map(this::findOtherObject)

.filter(this::isThisOtherObjectStale)

.map(this::convertToJson)

.map(String::trim)

.orElseThrow(() -> new RuntimeException("something went horribly wrong."));

通过以上这么多例子,相信我们已经深刻体会到了Optional的魔力,领略到了它的魅力。Java8 Optional类使Java程序更安全,防止代码被空值污染。想了解更多java8的新特点,可以观看本网站java8新特色专题课程,这里有你想学的一切。

上一篇 30道初级Java工程师面试题(附答案)
下一篇 掌握java方法覆盖的实现方法

文章素材均来源于网络,如有侵权,请联系管理员删除。