java出现空指针异常,java编写抛出空指针异常程序
程序中的变量为空,这意味着它没有引用或指针。这个时候,我们对这个变量做的任何操作,都不可避免的会引起一个NullPointerexception,也就是Java中的NullPointerException。那么,在什么情况下容易出现空指针异常,应该如何修复呢?
空指针异常虽然很烦人,但是很容易定位,比较麻烦的是搞清楚空的含义。比如客户端给服务器的一条数据为空,是打算给空值还是不提供值?比如数据库中字段的空值是否有特殊含义?针对数据库中的空值写SQL要特别注意什么?
今天就带着这些疑问,开始null踩坑之旅吧。
NullPointerException是Java代码中最常见的异常,我将其最可能出现的情况分为以下五类:
参数是Integer之类的打包类型,使用时会因为自动拆箱而出现空指针异常;字符串比较中出现空指针异常;ConcurrentHashMap等容器不支持空键和值,强制空键或空值会导致空指针异常;对象A包含B,通过对象A的字段获取B后,不判断字段null而级联调用B的方法出现空指针异常;或者方法的远程服务返回的列表不是null而是null,没有null判断直接调用列表的方法有null指针异常。private ListString error method(foo service foo service,Integer i,String s,String t){ log . info( result { } { } { } { } ,i 1,s.equals(OK ),s.equals(t),new ConcurrentHashMapString,String()。put(null,null));if (fooService.getBarService()。酒吧()。equals( OK ))log . info( OK );返回null} @ get mapping( error )public int error(@ request param(value= test ,default value= 1111 )String test){ return wrong method(test . charat(0)= 1 ?null : new FooService(),test.charAt(1)==1 ?null : 1,test.charAt(2)==1 ?null : OK ,test.charAt(3)==1 ?null :“OK”)。size();} class foo service { @ Getter private bar service bar service;} class bar service { String bar(){ return OK ;}}
修复思路如下:
对于整数的null判断,可以用Optional.ofNullable构造一个Optional,然后用or else(0)用默认值替换null再进行1运算。对于字符串和文字量的比较,可以把文字量放在前面,比如‘OK’。等于(s),这样即使s为空也不会出现空指针异常;对于两个可能为空的字符串变量的等于比较,可以使用Objects.equals,它将进行空判断。
对于ConcurrentHashMap,由于它的键和值不支持null,所以修复方法是不存储null。HashMap的键和值可以存储在null中,而ConcurrentHashMap看起来是HashMap的线程安全版本,但是不支持null值的键和值,这是容易产生误解的地方。
对于像fooService.getBarService()这样的级联调用。酒吧()。equals ("OK "),有很多地方需要null,包括fooservice的返回值,getbarservice()方法,bar方法返回的字符串。如果用if-else判断null可能需要几行代码,但是如果用Optional的话一行代码就够了。
对于rightMethod返回的列表,无法确认是否为null,所以在调用size方法获取列表大小之前,还可以用Optional.ofNullable将返回值包装起来,然后在列表为null时通过获得一个空列表。orElse(Collections.emptyList())实现,最后调用size方法。
lass="brush:java;">private List<String> rightMethod(FooService fooService, Integer i, String s, String t) { log.info("result {} {} {} {}", Optional.ofNullable(i).orElse(0) + 1, "OK".equals(s), Objects.equals(s, t), new HashMap<String, String>().put(null, null)); Optional.ofNullable(fooService) .map(FooService::getBarService) .filter(barService -> "OK".equals(barService.bar())) .ifPresent(result -> log.info("OK")); return new ArrayList<>();}@GetMapping("right")public int right(@RequestParam(value = "test", defaultValue = "1111") String test) { return Optional.ofNullable(rightMethod(test.charAt(0) == 1 ? null : new FooService(), test.charAt(1) == 1 ? null : 1, test.charAt(2) == 1 ? null : "OK", test.charAt(3) == 1 ? null : "OK")) .orElse(Collections.emptyList()).size();}我们根据业务需要分别对姓名、年龄和昵称进行更新:对于姓名,我们认为客户端传 null 是希望把姓名重置为空,允许这样的操作,使用 Optional 的 orElse 方法一键把空转换为空字符串即可。
对于年龄,我们认为如果客户端希望更新年龄就必须传一个有效的年龄,年龄不存在重置操作,可以使用 Optional 的 orElseThrow 方法在值为空的时候抛出 IllegalArgumentException。
对于昵称,因为数据库中姓名不可能为 null,所以可以放心地把昵称设置为 guest 加上数据库取出来的姓名。
@PostMapping("right")public UserEntity right(@RequestBody UserDto user) { if (user == null user.getId() == null) throw new IllegalArgumentException("用户Id不能为空"); UserEntity userEntity = userEntityRepository.findById(user.getId()) .orElseThrow(() -> new IllegalArgumentException("用户不存在")); if (user.getName() != null) { userEntity.setName(user.getName().orElse("")); } userEntity.setNickname("guest" + userEntity.getName()); if (user.getAge() != null) { userEntity.setAge(user.getAge().orElseThrow(() -> new IllegalArgumentException("年龄不能为空"))); } return userEntityRepository.save(userEntity);}
到此这篇关于Java中怎样处理空指针异常的文章就介绍到这了,更多相关Java 空指针异常内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。