(0!=0)==true? 记一个匪夷所思的问题
最近换了份工作,公司的开发框架是基于SSH自己搭建的。这个问题是我在解决一个需求的时候遇到的,其实解决这个疑惑的过程也就是读框架源码的过程,特此记录一下。
问题:ba.getState()!=CbBankAccount.STATE_NORMAL
在二者的类型都是Integer的且字面值均为0的情况下返回了true。
我们知道Java中整型的-128~127存在JVM的运行时常量池中,当比较处于这个范围的的整型值时比较的是字面值,反之比较的是引用堆中的对象的地址。
而在我遇到的情况下二者都是0。想到可能是在某处代码调用ba.setState(Integer i)赋值时做了手脚。
接下来就是跟代码的过程了。以下代码有部分删改。
ba先从数据库查出来,再从前台请求中获取对应字段赋值。
ba = (CbBankAccount) super.getBeanForUpdate(CbBankAccount.class, ba);
public <T> T getBeanForUpdate(Class<T> clazz, Object obj) {
Assert.notNull(obj);
Assert.notNull(clazz);
return HttpUtils.getBean(getRequest(), clazz, obj);
}
public static <T> T getBean(HttpServletRequest request, Class<T> c,
Object obj) {
Map<String, Object> paramMap = request.getParameterMap();
Object value = null;
Class[] paramTypes = new Class[1]; try {
Field[] f = c.getDeclaredFields();
List<Field[]> flist = new ArrayList<Field[]>();
flist.add(f);
Class superClazz = c.getSuperclass(); // 获取父类,如果父类存在则取父类的Field
while (superClazz != null) {
f = superClazz.getDeclaredFields();
flist.add(f);
superClazz = superClazz.getSuperclass();
}
for (Field[] temp : flist) {
for (Field field : temp) {
String fName = field.getName(); value = paramMap.get(fName);
if (value != null) {
paramTypes[0] = field.getType();
Method method = null;
StringBuffer methodName = new StringBuffer("set");
methodName.append(fName.substring(0, 1).toUpperCase());
methodName.append(fName.substring(1, fName.length()));
method = c.getMethod(methodName.toString(), paramTypes);
method.invoke(obj, getValue(request, fName,
paramTypes[0]));//从请求中获得字段对应值并赋值
} }
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} return (T) obj;
}
....
最终在转换数字的地方找到了答案(使用的是org.apache.commons.beanutils.converters.NumberConverter)
private Number toNumber(Class sourceType, Class targetType, Number value) { // Correct Number type already
if (targetType.equals(value.getClass())) {
return value;
} // Byte
if (targetType.equals(Byte.class)) {
long longValue = value.longValue();
if (longValue > Byte.MAX_VALUE) {
throw new ConversionException(toString(sourceType) + " value '" + value
+ "' is too large for " + toString(targetType));
}
if (longValue < Byte.MIN_VALUE) {
throw new ConversionException(toString(sourceType) + " value '" + value
+ "' is too small " + toString(targetType));
}
return new Byte(value.byteValue());
} // Short
if (targetType.equals(Short.class)) {
long longValue = value.longValue();
if (longValue > Short.MAX_VALUE) {
throw new ConversionException(toString(sourceType) + " value '" + value
+ "' is too large for " + toString(targetType));
}
if (longValue < Short.MIN_VALUE) {
throw new ConversionException(toString(sourceType) + " value '" + value
+ "' is too small " + toString(targetType));
}
return new Short(value.shortValue());
} // Integer
if (targetType.equals(Integer.class)) {
long longValue = value.longValue();
if (longValue > Integer.MAX_VALUE) {
throw new ConversionException(toString(sourceType) + " value '" + value
+ "' is too large for " + toString(targetType));
}
if (longValue < Integer.MIN_VALUE) {
throw new ConversionException(toString(sourceType) + " value '" + value
+ "' is too small " + toString(targetType));
}
return new Integer(value.intValue());
} // Long
if (targetType.equals(Long.class)) {
return new Long(value.longValue());
} // Float
if (targetType.equals(Float.class)) {
if (value.doubleValue() > Float.MAX_VALUE) {
throw new ConversionException(toString(sourceType) + " value '" + value
+ "' is too large for " + toString(targetType));
}
return new Float(value.floatValue());
} // Double
if (targetType.equals(Double.class)) {
return new Double(value.doubleValue());
} // BigDecimal
if (targetType.equals(BigDecimal.class)) {
if (value instanceof Float || value instanceof Double) {
return new BigDecimal(value.toString());
} else if (value instanceof BigInteger) {
return new BigDecimal((BigInteger)value);
} else {
return BigDecimal.valueOf(value.longValue());
}
} // BigInteger
if (targetType.equals(BigInteger.class)) {
if (value instanceof BigDecimal) {
return ((BigDecimal)value).toBigInteger();
} else {
return BigInteger.valueOf(value.longValue());
}
} String msg = toString(getClass()) + " cannot handle conversion to '"
+ toString(targetType) + "'";
if (log().isWarnEnabled()) {
log().warn(" " + msg);
}
throw new ConversionException(msg); }
return new Integer(value.intValue());创建了一个新的对象。故出现了上边的问题。
遇到问题还是要跟源码分析才能得到结果啊!
(0!=0)==true? 记一个匪夷所思的问题的更多相关文章
- console.log(0.2+0.4===0.6)// true or false??
在正常的数学逻辑思维中,0.2+0.4===0.6这个逻辑是正确的,但是在JavaScript中0.2+0.4!==0.6这是为什么呢?这个问题也会偶尔被用来当做面试题来考查面试者对 JavaScri ...
- 从 0 开始手写一个 Mybatis 框架,三步搞定!
阅读本文大概需要 3 分钟. MyBatis框架的核心功能其实不难,无非就是动态代理和jdbc的操作,难的是写出来可扩展,高内聚,低耦合的规范的代码. 本文完成的Mybatis功能比较简单,代码还有许 ...
- 未能加载文件或程序集“Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件
发布的打包项目在本机测试好使,部署到客户服务器上报错 分析器错误消息: 未能加载文件或程序集“Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Cu ...
- 用Scratch2.0源码定制一个自己的编辑器
用Scratch2.0源码定制一个自己的编辑器,换成自己的软件名称和图标,添加中文字体,修复汉化错误等等1.准备:下载Scratch2.0源码.安装开发工具Adobe Flash Builder4.7 ...
- Oracle 远程访问配置 在 Windows Forms 和 WPF 应用中使用 FontAwesome 图标 C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素” C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper Decimal类型截取保留N位小数向上取, Decimal类型截取保留N位小数并且不进行四舍五入操作
Oracle 远程访问配置 服务端配置 如果不想自己写,可以通过 Net Manager 来配置. 以下配置文件中的 localhost 改为 ip 地址,否则,远程不能访问. 1.网络监听配置 ...
- LinkedHashMap<String, Bitmap>(0, 0.75f, true) LinkedHashMap的加载因子和初始容量分配
今天上午在CSDN的论坛里看到有朋友提的问题如下: /** @param maxSize Maximum sum of the sizes of the Bitmaps in this cache * ...
- Go语言之从0到1实现一个简单的Redis连接池
Go语言之从0到1实现一个简单的Redis连接池 前言 最近学习了一些Go语言开发相关内容,但是苦于手头没有可以练手的项目,学的时候理解不清楚,学过容易忘. 结合之前组内分享时学到的Redis相关知识 ...
- 使用react+redux+react-redux+react-router+axios+scss技术栈从0到1开发一个applist应用
先看效果图 github地址 github仓库 在线访问 初始化项目 #创建项目 create-react-app applist #如果没有安装create-react-app的话,先安装 npm ...
- 从0到1发布一个npm包
从0到1发布一个npm包 author: @TiffanysBear 最近在项目业务中有遇到一些问题,一些通用的方法或者封装的模块在PC.WAP甚至是APP中都需要使用,但是对于业务的PC.WAP.A ...
随机推荐
- kali linux之手动漏洞挖掘三(sql注入)
服务器端程序将用户输入作为参数作为查询条件,直接拼写sql语句,并将结果返回给客户端浏览器 如判断登录 select * from users where user='uname' and passw ...
- GitHub 十大 CI 工具
简评:GitHub 上最受欢迎的 CI 工具. 持续集成(Continuous integration)指的是,频繁地(一天多次)将代码集成到主干. 持续集成工具让产品可以快速迭代,同时还能保持高质量 ...
- Python中实现简单的插件框架
在系统设计中,经常我们希望设计一套插件机制,在不修改程序主体情况下,动态去加载附能. 我设想的插件系统: 1.通过类来实现 2.自动查找和导入 我们假设需要实现一个简单的插件系统,插件可以接收一个参数 ...
- flink学习笔记-split & select(拆分流)
说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...
- setinterval 里面的方法记得加引号
setinterval 里面的方法记得加引号 否则不执行
- Qt 学习之路 2(34):贪吃蛇游戏(4)
Qt 学习之路 2(34):贪吃蛇游戏(4) 豆子 2012年12月30日 Qt 学习之路 2 73条评论 这将是我们这个稍大一些的示例程序的最后一部分.在本章中,我们将完成GameControlle ...
- bzoj3262 陌上花开 cdq分治(入门)
题目传送门 思路:cdq分治处理偏序关系的模板题,主要就是学cdq分治吧,还在入门中. 代码其实也很好理解,记得树状数组操作的上限是 z的最大值,不是n的最大值,这个细节wa了好久. #include ...
- bzoj1076 奖励关 期望dp
题目传送门 题目大意:总共有k次弹出宝物的机会,宝物共有n种,弹出不同的宝物的概率相同的,是每个宝物都有价值,和选择这个宝物的限制(必须具有特定的宝物),问最后的最优期望是多少. 思路:“正向推概率, ...
- VBS虚拟键盘十六进制列表
Set WshShell=WScript.CreateObject("WScript.Shell") '打开我的电脑WshShell.Sendkeys chr(&h88b6 ...
- 利用touchslide实现tab滑动切换
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...