关于Integer.valueOf(param)报空指针

本文探讨了一种在Java中使用Integer.valueOf()方法时遇到的空指针异常问题,并通过详细的代码示例解释了异常产生的原因。作者通过一系列实验发现了问题的根源在于自动拆箱过程中的空值处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天遇到了一个很奇葩的错误,大致现象如下:

Integer unfinishedQty = Integer.valueOf(obj.getTaskQty()) - 0;

程序中有一行类似于这样的代码,报了个“空指针异常”,我还问了老同事,valueOf不是不会报空指针么?同事说不会,就算报异常,也应该会报 java.lang.NumberFormatException,数字转换异常。可是,这一行确实报了空指针,但是有一点我可以肯定,obj这个对象肯定是不为null的,不然走不到这一行,原因我就不多说了。

后来经过多种调试(当时以为传入valueOf中的参数是字符串类型的),调试如下:

public static void main(String[] args) {
System.out.println(Integer.valueOf(null));
}

java.lang.NumberFormatException;

然后又试了试,以为可能得给参数一个变量,于是有了如下测试:

public static void main(String[] args) {

String a = null;
System.out.println(Integer.valueOf(a));
}

还是报java.lang.NumberFormatException;

就是不报空指针;后来经过查看,发现代码中传入的参数是Integer类型的,于是不死心,又试了一下:

public static void main(String[] args) {

Integer a = null;
System.out.println(Integer.valueOf(a));
}

果然,报了空指针,但是一直想不明白,后来查看了valueOf源代码:

入参为String类型:

 public static Integer valueOf(String s) throws NumberFormatException
    {
return new Integer(parseInt(s, 10));
    }

入参为int类型:

  public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache 
    return IntegerCache.cache[i + offset];
}
        return new Integer(i);
    }

我的代码中调用的为int类型入参的valueOf,而我传参穿的为Integer类型的,在真正调用该方法前,编译时会自动将Integer拆箱成Int类型的,而int类型变量值的不能为null,所以在拆箱的过程中,报了空指针异常。

这个问题我也真是费解了半天呀。希望对大家有所帮助,如果哪里不太正确,欢迎纠错。

请你仿照package com.app.service.impl; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.app.dao.ConfigDao; import com.app.entity.ConfigEntity; import com.app.service.ConfigService; import org.springframework.stereotype.Service; import java.util.Map; @Service("configService") public class ConfigServiceImpl extends ServiceImpl<ConfigDao, ConfigEntity> implements ConfigService { @Override public Page<ConfigEntity> queryPage(Map<String, Object> params, Wrapper<ConfigEntity> wrapper) { // 安全地将Wrapper转换为QueryWrapper QueryWrapper<ConfigEntity> queryWrapper = convertToQueryWrapper(wrapper); // 分页参数处理 long pageNum = 1; long pageSize = 10; if (params.get("page") != null) { try { pageNum = Long.parseLong(String.valueOf(params.get("page"))); } catch (NumberFormatException e) { // 使用默认值 } } if (params.get("limit") != null) { try { pageSize = Long.parseLong(String.valueOf(params.get("limit"))); } catch (NumberFormatException e) { // 使用默认值 } } // 创建分页对象 Page<ConfigEntity> page = new Page<>(pageNum, pageSize); return baseMapper.selectPage(page, queryWrapper); } /** * 将Wrapper安全转换为QueryWrapper * @param wrapper 原始Wrapper对象 * @return 转换后的QueryWrapper */ private QueryWrapper<ConfigEntity> convertToQueryWrapper(Wrapper<ConfigEntity> wrapper) { if (wrapper instanceof QueryWrapper) { return (QueryWrapper<ConfigEntity>) wrapper; } return new QueryWrapper<>(wrapper.getEntity()); } } 给出package com.app.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.app.dao.DictionaryDao; import com.app.entity.DictionaryEntity; import com.app.service.DictionaryService; import jakarta.servlet.ServletContext; import jakarta.servlet.http.HttpServletRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 字典表服务实现类 */ @Service("dictionaryService") @Transactional public class DictionaryServiceImpl extends ServiceImpl<DictionaryDao, DictionaryEntity> implements DictionaryService { @Override public Page<DictionaryEntity> queryPage(Map<String, Object> params, QueryWrapper<DictionaryEntity> wrapper) { // 分页参数处理 long pageNum = 1; long pageSize = 10; if (params.get("page") != null) { pageNum = Long.parseLong((String) params.get("page")); } if (params.get("limit") != null) { pageSize = Long.parseLong((String) params.get("limit")); } // 创建分页对象 Page<DictionaryEntity> page = new Page<>(pageNum, pageSize); return baseMapper.selectPage(page, wrapper); } @Override public void dictionaryConvert(Object obj, HttpServletRequest request) { try { if (obj == null) return; // 获取所有以"Types"结尾的字段 List<String> fieldNameList = new ArrayList<>(); Class<?> tempClass = obj.getClass(); while (tempClass != null) { for (Field f : tempClass.getDeclaredFields()) { f.setAccessible(true); if (f.getType().equals(Integer.class) && f.getName().endsWith("Types")) { fieldNameList.add(f.getName()); } } tempClass = tempClass.getSuperclass(); } // 获取ServletContext中的字典数据 ServletContext servletContext = request.getServletContext(); Map<String, Map<Integer, String>> dictionaryMap = (Map<String, Map<Integer, String>>) servletContext.getAttribute("dictionaryMap"); // 为每个字段赋值 for (String fieldName : fieldNameList) { Field typesField = null; Field valueField = obj.getClass().getDeclaredField(fieldName.replace("Types", "Value")); valueField.setAccessible(true); // 获取Types字段 if (hasField(obj.getClass(), fieldName)) { typesField = obj.getClass().getDeclaredField(fieldName); } else if (obj.getClass().getSuperclass() != null && hasField(obj.getClass().getSuperclass(), fieldName)) { typesField = obj.getClass().getSuperclass().getDeclaredField(fieldName); } if (typesField == null) continue; typesField.setAccessible(true); Integer typeValue = (Integer) typesField.get(obj); // 转换字段名为下划线格式 String dictKey = toUnderScoreCase(fieldName); // 赋值 if (typeValue != null && dictionaryMap.containsKey(dictKey)) { String dictValue = dictionaryMap.get(dictKey).get(typeValue); valueField.set(obj, dictValue); } else { valueField.set(obj, ""); } } } catch (Exception e) { e.printStackTrace(); } } private String toUnderScoreCase(String camelCase) { StringBuilder sb = new StringBuilder(); for (char c : camelCase.toCharArray()) { if (Character.isUpperCase(c)) { sb.append('_').append(Character.toLowerCase(c)); } else { sb.append(c); } } return sb.toString(); } private boolean hasField(Class<?> clazz, String fieldName) { for (Field f : clazz.getDeclaredFields()) { if (f.getName().equals(fieldName)) { return true; } } return false; } }修改过后的完整代码
最新发布
07-12
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值