Java中NullPointerException的完善解决方案
null在Java中带来的贫苦
我信赖所有的Java程序猿一定都遇到过NullPointerException
,空指针在Java程序中是最常见的,也是最烦人的;它让我们许多程序猿发生了根深蒂固的感受,所有可能发生空指针的地方都的加上if-else
检查,然则这带给我们许多贫苦
- Java自己是强类型的,然则null破坏了这个规则,它可以被赋值给任何工具
- Java的设计是让程序猿对指针无感知,然则null指针是个破例
- 它会是代码变得很臃肿,到处都充斥着
if-else
的空检查,甚至是多层嵌套,代码可读性下降 - null自己毫无意义,示意不了
无
前两点不需要稀奇的说明,后两点举个例子来说明一下:
若是一个人拥有一个手机,每个手机都有天生厂商,每个厂商都市有个名字,用类示意的话:
public class Person {
private Phone phone;
public Phone getPhone() {
return phone;
}
}
public class Phone {
private Producer producer;
public Producer getProducer() {
return producer;
}
}
public class Producer {
private String name;
public String getName() {
return name;
}
}
在这个例子中,若是我们需要取到手机天生厂商的名字
public String getPhoneProducerName(Person person) {
return person.getPhone().getProducer().getName();
}
由于不一定每个人都市有一个手机,所有在挪用getProducer()
时可能会泛起NullPointerException
。
一门设计语言原本就是来形貌天下的,在这个事例中有的人有手机,有的人也可能没有手机,以是在挪用person.getPhone()
返回的值就应该包罗有和无这两种情形,现在通过返回null
来示意无,然则在挪用getProducer()
却又会抛出异常,这样就不太相符现实逻辑;以是把null
来用来示意无
不合适
在遇到这种情形通常的做法是做null检查,甚至是每个地方可能发生null指针的做检查。
public String getPhoneProducerName(Person person) {
if (person.getPhone() == null) {
return "无名字";
}
if (person.getPhone().getProducer() == null) {
return "无名字";
}
return person.getPhone().getProducer().getName();
}
这里我已经试图在削减代码的层级,若是使用的是if-else
,代码的层级会更深,代码可读性下降。
Optional的简朴先容
吐槽了那么多现状的欠好,现在可以祭出我们的解决方案了 Optional
;千呼万唤始出来,犹抱琵琶半遮面;那Optional
到底是个什么东西,我们一起来逐步解开它的面纱。
Optional
自己只是对工具的简朴包装,若是工具为空,那么会构建一个空的Optional
;这样一来Optional
就包罗了存在和不存在两个情形, 接下来可以看下上面的例子悔改之后
public class Person {
private Optional<Phone> phone;
public Optional<Phone> getPhone() {
return phone;
}
}
public class Phone {
private Producer producer;
public Producer getProducer() {
return producer;
}
}
public class Producer {
private String name;
public String getName() {
return name;
}
}
由于有的人可能没有手机,有的人有,以是Phone
需要用Optional
包装起来;手机自己一定会有生产的厂商,厂商一定会有一个名字,以是这两个不需要用Optional
包装起来。这里我们会发现使用了Optional
会厚实代码的语义,让代码加倍相符现实。
,欢迎进入欧博allbet注册(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。
而当我们在挪用phone.getProducer().getName()
的时刻不需要做null指针的检查,若是说在这里发生了NullPointerException
,说明这里数据自己是有问题的,不相符现实,就应该让问题露出出来,而不是像上面的代码一样把问题掩饰。
Optional的常用方式使用
1. Optional的建立方式
Optional<Person> empty = Optional.empty(); //声名一个空的Optional
Optional<Person> person = Optional.of(new Person()); //包装Person
Optional<Person> person2 = Optional.of(null); //不允许的操作,传入null 会抛出空指针异常
Optional<Person> optionalPerson = Optional.ofNullable(null); //允许传null, 返回一个空的Optional
2. Optional值的获取方式
- map、flatMap
首先我们重新界说一下Phone类,除了有生产厂商之外,另有个型号;
public class Phone {
private String model;
private Producer producer;
public Producer getProducer() {
return producer;
}
public String getModel() {
return model;
}
}
当我们需要获取到手机的型号的时刻可以这样:
Optional<Phone> optionalPhone = Optional.of(new Phone());
Optional<String> model = optionalPhone.map(Phone::getModel);
当我们需要通过Person工具获取到Phone的型号是,会想到这样:
Optional<Person> optionalPerson = Optional.of(new Person());
optionalPerson.map(Person::getPhone).map(Phone::getModel);
当我们写出来的时刻发现编译器不能通过。是由于Person::getPhone
返回的是一个Optional<Phone>
,挪用optionalPerson.map(Person::getPhone)
返回的就是Optional<Optional<Phone>>
,以是再.map
的就无法拿到手机型号,那若何能够让返回的效果不是Optional<Optional<Phone>>
,而是Optional<Phone>
呢?
这里需要用到另一个方式flatMap
。flatMap
和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));
}
}
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
map
方式在返回的时刻会包装一层Optional
; flatMap
在返回的时刻直接把函数的返回值返回了,函数的效果必须是Optional
;那么在前面的例子中我们直接挪用flatMap
返回的效果就是Optional<Phone>
Optional<Person> optionalPerson = Optional.of(new Person());
optionalPerson.flatMap(Person::getPhone).map(Phone::getModel);
-
取出
Optional
中的值工具:get、orElse、orElseGet、orElseThrow、ifPresent- get() : 当你明确知道Optional中有值的话可以直接挪用该方式,当Optional中没有值是该方式会抛出异常
NoSuchElementException
;以是当若是存在空值的话建议就不要挪用该方式,由于这样和做null检查就没有区别了 - orElse(T other) : 提供一个默认值,当值不存在是返回这个默认值
- orElseGet(Supplier<? extends T> other) : 当值不存在的时刻会挪用supper函数,若是说返回这个默认值的逻辑较多,那么挪用这个方式对照合适;
- orElseThrow(Supplier<? extends X> exceptionSupplier) : 当值为空时会抛出一个自界说的异常
- ifPresent(Consumer<? super T> consumer) : 当值不为空是会挪用
consumer
函数,若是值为空,那么这个方式什么都不做
- get() : 当你明确知道Optional中有值的话可以直接挪用该方式,当Optional中没有值是该方式会抛出异常
- filter 过滤出知足条件的工具
若是我们需要过滤脱手机型号IOS
的手机,并打印出型号,代码如下:
Person person = new Person(Optional.of(new Phone("IOS")));
Optional<Person> optionalPerson = Optional.of(person);
optionalPerson.flatMap(Person::getPhone)
.filter(phone -> "IOS".equals(phone.getModel()))
.map(Phone::getModel)
.ifPresent(System.out::println);
总结
- 我们讨论了null在Java程序的问题
- 先容Java8中引入了
Optional
来示意有和无的情形以及初始化的方式 - 举例说明了
Optional
中经常使用到的方式
本人菜鸟,若是有任何写的纰谬的地方,迎接在谈论区指出
原创不易 转载请注明出处:https://silently9527.cn/archives/56
0
珍藏
阳光在线(原诚信在线官网现平心在线)现已开放阳光在线电脑版、手机版下载、企业邮局登录、会员开户、代理合作等服务。不看电视了,看你
阳光在线(原诚信在线官网现平心在线)现已开放阳光在线电脑版、手机版下载、企业邮局登录、会员开户、代理合作等服务。不看电视了,看你
365资讯网365资讯网资讯网:国内领先的大数据推荐,新闻头条、体育报道、财经报道、游戏评测、硬件评测、健康养生等资讯。怎么会不喜欢
这些都是可以一招鲜吃遍天的阵容。大家怎么看待这版本的海盗体系?
转载说明:本文转载自USDT交易平台。我真觉得可以更好
随着今年新一代处理器的普及化,在效能显示与功耗相较于去年之前的旧版本也有显著的差异,也因此在今年新购置轻薄笔电的同伙,笔者也会建议可以选择新版本处理器的机种,现在市面上主流的选择会是第十代的 Intel Core i5 与 Core i7 系列。此外,记忆体也建议至少选择 8GB、最理想是选择 16GB 的规格,储存装备也以 PCIe NVMe 规格的 SSD 为主。 此外,在笔电的无线网路方面,也建议选择新规格的 Wi-Fi 6,搭配统一世代的无线路由器时,能有更好的效能显示。赞,转,评,常规流程
这个小站也挺好的