在开发过程中我们难免遇到Java给我们报NullPointerException,比如们直接看一个简单的例子。
public class NullDemo{
public static void main(String[] args) {
MessageUtil.useMessage(MessageUtil.getMessage());
}
}
interface IMessage{
public String getContent() ;
}
class MessageImpl implements IMessage{
@Override
public String getContent() {
return "www.baidu.com" ;
}
}
class MessageUtil{
private MessageUtil(){
}
public static IMessage getMessage(){
IMessage msg = new MessageImpl() ;
return msg ;
}
public static void useMessage(IMessage msg){
System.out.println(msg.getContent());
}
}
在上面的代码中我们使用接口实现类MessageImpl获取了信息,在工具类中使用一个工厂设计模式方法获取接口实现类的实例化对象,使用另一个方法从实现类中获取信息。
在主方法中使用工厂生产实例化对象,将对象作为参数传入到获取信息的方法中。
上面的代码看起来很完美,但这只是一个简单的例子,在实际的开发之中我们遇到的情况要复杂的多,比如getMessage()方法,如果我们获取不到实例化对象,返回一个Null会怎么样呢?
class MessageUtil{
private MessageUtil(){
}
public static IMessage getMessage(){
return null ;
}
public static void useMessage(IMessage msg){
System.out.println(msg.getContent());
}
}
Exception in thread “main” java.lang.NullPointerException
at dataStructure.MessageUtil.useMessage(NullDemo.java:30)
at dataStructure.NullDemo.main(NullDemo.java:7)
我们来观察一下异常信息,可以看到,虽然问题出现在getMessage(),他返回了null,但是报错确是useMessage()方法。那么有没有什么方法解决这一点呢?
class MessageUtil{
private MessageUtil(){
}
public static IMessage getMessage(){
return null ;
}
public static void useMessage(IMessage msg){
if(msg != null)
System.out.println(msg.getContent());
}
}
传统上我们在执行方法的时候做一个参数是否为null的判断,如果是的话直接跳过执行,运行代码我们也发现并没有报错。但是这样不好。这就像是我们去银行取钱,银行的职员不负责给出的钱是真的,而要我们顾客自己判断,在一个大型的项目中,每一个方法都进行判断的话,代码太过于冗余,所以我们应该将问题扼杀在摇篮中
这里的摇篮就是我们的工厂getMessage()方法,如果能保证其总是给出正确的实例化对象,我们也没有这许多烦恼。
好在java在1.8的时候提供了一个方法供我们处理空对象,我们来看一段代码
class MessageUtil{
private MessageUtil(){
}
public static Optional<IMessage> getMessage(){
return Optional.of(new MessageImpl()) ;
}
public static void useMessage(IMessage msg){
if(msg != null)
System.out.println(msg.getContent());
}
}
Exception in thread “main” java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at dataStructure.MessageUtil.getMessage(NullDemo.java:27)
at dataStructure.NullDemo.main(NullDemo.java:7)
在这段代码的生产实例化对象过程中,我们加入了一个Optional.of()判断,这个时候我们传入一个空对象,可以看到在控制台,java的报错从useMessage()方法,变成了getMessage()方法,回到刚才银行的例子中,我们可以说将判断假币的工作从客户转移到了银行职员。
Optional当然是不仅仅在生产的时候判断空对象,他同样可以对空对象进行处理。我们看一段代码
public class NullDemo{
public static void main(String[] args) {
MessageUtil.useMessage(MessageUtil.getMessage().orElse(new MessageImpl()));
}
}
interface IMessage{
public String getContent() ;
}
class MessageImpl implements IMessage{
@Override
public String getContent() {
return "www.baidu.com" ;
}
}
class MessageUtil{
private MessageUtil(){
}
public static Optional<IMessage> getMessage(){
return Optional.ofNullable(null) ;
}
public static void useMessage(IMessage msg){
if(msg != null)
System.out.println(msg.getContent());
}
}
在这段代码中我们将判断空对象的语句变成Optional.ofNullable()方法,这个方法意味着我们可以传入空对象,在主方法中,我们使用orElse()方法接收参数,这意味着如果我们实例化对象就直接用,收到空对象则自己生产实例化对象。
那么到这里Optional类我们就说完啦!