前言

在项目中随手把haseMap改成了currenHaseMap差点被公司给开除了。

判断相等

字符串判断相等
        String str1 = null;
String str2 = "java金融";
// str1.equals(str2); 错误的写法
str2.equals(str1); // 常量写前面
Objects.equals(str1, str2);// 借助jdkUtil工具类
StringUtils.equals(str1,str2); // 自定义工具类
  • 字符串判断相等我们记住一定要常量写前面。
  • 借助jdk提供的util帮助类(Objects)。
  • 自定义工具类,进行判空处理。
包装类判断相等
        Integer n1 = 100;
Integer n2 = 100;
System.out.println(n1 == n2);//true
System.out.println(n1.equals(n2));//true
Integer n3 = 200;
Integer n4 = 200;
System.out.println(n3 == n4);//false
System.out.println(n3.equals(n4));//true

为什么n3== n4 是false呢?由于包装类的缓存机制。

包装类的比较用equals去判断。

最推荐的还是用工具类去判断。例如上面的列子如果n3=null的话n3.equals(n4)这时候就会抛出npe了。如果用工具类的话就不会存在这种情况。总之一句话判断相等如果不愿意去判空(偷懒、代码也不好看)就借助工具类。合理使用工具类可以使你的代码减少不必要的npe。

三目运算符

这个常见的坑的话就是由于自动拆箱导致的 NPE 异常。这个阿里巴巴开发手册(需要这个手册可以关注公众号回复"JAVA")说的很明白了。

BigDecimal

禁止使用浮点数double,float的初始化
        double d = 1.001;
float f = 1.001f;
BigDecimal bigDecimal1 = new BigDecimal(d);
BigDecimal bigDecimal2 = new BigDecimal(f);
System.out.println(bigDecimal1);
System.out.println(bigDecimal2);

输出结果

1.000999999999999889865875957184471189975738525390625
1.00100004673004150390625

这个结果是不是跟我们所期望的1.001有点不一样。

float和double可以用于工程计算科学计算,他们会有精度丢失,这是由于浮点运算器的结构导致的,但是在金融领域一旦精度出现问题就意味着可能是严重的现实经济损失,所以普通的那些数值型一般不会在这个场景下使用。

所以涉及金钱的计算一定不要使用float和double。使用BigDecimal并且一定要用String来构造。 上面的列子我们可以这样来初始化 new BigDecimal(“1.001”)。

进行除法运算时必须要设置保留小数位
		BigDecimal a = new BigDecimal("1");
System.out.println(a.divide(new BigDecimal(3)));

输出

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1690)
at com.workit.demo.antisper.Test.main(Test.java:11)

解决办法:使用如下两个函数设置精度

  • divide(num, scale)
  • divide(num, scale, roundingMode)
        BigDecimal a = new BigDecimal("1");
System.out.println(a.divide(new BigDecimal(3), 2,BigDecimal.ROUND_HALF_UP));

字符串分隔(别忘了转义)

        String str = "java|php|c++";
String[] split = str.split("|");
for(String s:split){
System.out.println(s);
}

输出结果

j
a
v
a
|
p
h
p
|
c
+
+

结果并不是我们所期待的,java、php、c++。

解决办法我们对|进行转义分割,代码改为 String[] split = str.split("\|");结果就正确了。

String的split方法需要转义的字符串:. $ | ( ) [ { ^ ? * + \ 共12个特殊字符,遇到以这些字符进行分割字符串的时候,需要在这些特殊字符前加双反斜杠\ \。

Arrays.asList 需要谨慎使用

下面列举一些常用但是却与我们所期待的结果不一样的用法。

将基本类型数组作为asList的参数
 		int[] array = {1,2,3};
List list = Arrays.asList(array);
System.out.println(list.size()); //1

输出的结果是1不是3哦是不是跟想象的有点不一样?原因如下:

由于Arrays.ArrayList参数为可变长泛型,而基本类型是无法泛型化的,所以它把int[] array 数组当成了一个泛型对象,所以集合中最终只有一个元素array 。

将数组作为asList参数后,修改数组或List
        String[] array = {"欢迎","关注","java金融"};
List list = Arrays.asList(array);
array[0] ="修改数组第一个元素";
list.set(2,"修改集合第三个元素");
System.out.println(Arrays.toString(array));
System.out.println(list.toString());

输出结果

[修改数组第一个元素, 关注, 修改集合第三个元素]
[修改数组第一个元素, 关注, 修改集合第三个元素]

是不是也与我们所期待的不一样。修改了数组奥了的值居然影响到了集合里面的值。原因如下:

由于asList产生的集合元素是直接引用作为参数的数组,所以当外部数组或集合改变时,数组和集合会同步变化,这在平时我们编码时可能产生莫名的问题。

数组转换为集合后,进行增删元素。
         String[] array = {"欢迎","关注","java金融"};
List list = Arrays.asList(array);
list.add("java金融");
System.out.println(list.toString());

输出结果:

Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)

抛出异常原因:由于asList产生的集合并没有重写add,remove等方法,所以它会调用父类AbstractList的方法,而父类的方法中抛出的却是异常信息。

当我们使用Arrays.asList 产生的集合时候,需要谨慎的去使用。如果需要对集合进行操作的时候我们可以通过 List list = new ArrayList(Arrays.asList(array)); 来进行使用。

currenHaseMap注意 key和value的null值
       String key = "java金融";
Map<String,Object> map = new ConcurrentHashMap<>();
map.put("1","2");
map.put(key,null);// Exception in thread "main" java.lang.NullPointerException

记得刚开始工作的时候,我负责的一个管理系统里面有一个关于省份的缓存,用HashMap来存的。大概就是项目一起动,然后就从db里面把省份信息加载到HashMap里面,以后需要用到省份信息直接从HashMap里面取,HashMap不是线程不安全吗?然后我反手就把它改成了currenHaseMap。测试环境测试没问题,然后就跟着其他功能上线。上完线之后也没有去回归关于省份的这一块内容,然后就下班了。第二天上班运营反映有部分注册用户的省份信息没了。leader就找我昨天有没有改过关于省份的代码,我说就改了一个currenHaseMap。leader先让昨天上线代码回退,一回退省份信息就有了。后面经过仔细排查原来生产数据库有一条省份信息是空的。然后加载那条空的省份信息到currenHaseMap就报空指针了,在这条空记录后面信息就没加载到currenHaseMap了。幸好是内网管理系统没有造成太大的影响 。

string.valueof

    String  userName= String.valueOf(parmMap.get("userName"));
if(StringUtils.isNotBlank(userName)) {
sql.append(" and tt.userName like %").append(userName);
}

这里的 parmMap.get(“userName”) 如果是 null , 那么这里的 userName就是 “null” ,这是一个值为 null 的字符串。导致数据会拼接到SQL 中,导出出错。为什么会这样我们看下源码就知道了。

 public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}

所以转字符串的时候我们要根据实际的情况来选择合适的方法。

总结

本文列举了一些对于java常见的一些可能稍微不注意就会采坑的一些知识点。还有其他更多需要注意的知识点也欢迎大家来补充。其实这些常见的采坑基本上只要去看下源码都能够避免的。

结束

  • 由于自己才疏学浅,难免会有纰漏,假如你发现了错误的地方,还望留言给我指出来,我会对其加以修正。
  • 如果你觉得文章还不错,你的转发、分享、赞赏、点赞、留言就是对我最大的鼓励。
  • 感谢您的阅读,十分欢迎并感谢您的关注。

在项目中随手把haseMap改成了currenHaseMap差点被公司给开除了。的更多相关文章

  1. VS2010中如何将动态链接库改成静态链接库

    VS2010中如何将动态链接库改成静态链接库 VS2010静态编译生成的.exe可执行文件,可以免安装免DLL在其他电脑直接运行. 静态编译:就是在编译可执行文件的时候,将可执行文件需要调用的对应动态 ...

  2. OpenGL ES SL 3.0规范中以前的attribute改成了in varying改成了out

           OpenGL ES和OpenGL的图标 关于“OpenGL ES SL 3.0规范中以前的attribute改成了in varying改成了out”这个问题,做一阐述: 1.关键字的小修 ...

  3. Maven项目中,编译proto文件成Java类

    新建Maven项目 新建一个 Maven 项目: pom定义了最小的maven2元素,即:groupId,artifactId,version. groupId:项目或者组织的唯一标志,并且配置时生成 ...

  4. Vue项目中导入excel文件读取成js数组

    1. 安装组件 cnpm install xlsx --save 2. 代码 <template> <span> <input class="input-fil ...

  5. 用linux的shell脚本把目录下面的所有文件的文件内容中的小写字母改成大写字母

    最近工作中,产品组的同事给出的数据里面都是小写字母 ,但是引擎组的同事要求他们拿到的从数据里面解析出的结构体里面存储的要都是大写结构,这让我们数据预处理组很尴尬啊,,所以在写了个这么样的脚本,在解析数 ...

  6. 把JavaScript代码改成ES6语法不完全指南

    目录 * 核心例子 * 修改成静态变量(const)或块级变量(let) * 开始修改 * 疑问解释(重复定义会发生什么) * 疑问解释(let的块级作用域是怎样的) * 疑问解释(const定义的变 ...

  7. 在JavaWeb项目中处理静态文件或动态链接拼接网站地址的最优处理方案

    在开发网站时候我们会遇到下面问题? - 在引用网页中引用js和css或者动态的Servlet的时候我们是写绝对路径还是相对路径? - 如果写相对路径吧,上线偶尔会报404,还要手动去拼接绝对路径 - ...

  8. 项目中常用js方法整理common.js

    抽空把项目中常用js方法整理成了common.js,都是网上搜集而来的,大家一起分享吧. var h = {}; h.get = function (url, data, ok, error) { $ ...

  9. java将url里面的中文改成ASCII字符集 和 SCII字符集 改成 中文

    package com.example.demo; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; / ...

随机推荐

  1. C语言中connst用法

    1.const一般用来定义只读变量,这个变量的之只能在初始化时赋值,如果初始化时没有赋值,则默认为0.如果在其他地方试图更改此值,编译会报错.如: 1 #include<stdio.h> ...

  2. Alpha冲刺-第六次冲刺笔记

    Alpha冲刺-冲刺笔记 这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzzcxy/2018SE2 这个作业要求在哪里 https://edu.cnblogs. ...

  3. od中低位地址和高位的顺序,以及数据的存放读写

    在观察内存的时候应当注意"内存数据"与"数值数据"的区别. 在我们的调试环境中,内存由低到高分布,你可以简单地把这种情形理解成Win32系统在内存中由地位向高位 ...

  4. mySQL入门之多表操作

    外键 初识外键 外键:引用另一个表中的一列或多列,被引用的列应该具有主键约束或唯一性约束.(外键用于建立和加强两个表数据之间的连接,保证数据的完整和统一性) 主表:被引用的表 从表:引用外键的表 -- ...

  5. Python中repr(变量)和str(变量)的返回值有什么区别和联系

    Python中repr(变量)和str(变量)都返回一个描述对象的字符串,二者有关联又有不同.由于Python3.0后都是新式类,我们的分析也是基于新式类进行的.基于object派生的新式类中二者之间 ...

  6. 第15.37节 PyQt(Python+Qt)入门学习:containers容器类部件QMdiArea多文档界面部件详解及编程开发案例

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 老猿在前期学习PyQt相关知识时,对每个组件的属性及方法都研 ...

  7. 第9.7节 Python使用write函数写入文件内容

    一. 语法 write(data) data为要写入的数据,可以为字符串str类型,也可以是bytes类型. 返回值为实际写入的数据数,在写入数据为str类型时,该数据为实际写入的UNIOCODE字符 ...

  8. AWD不死马与克制方法

    一个简单的不死马如: <?php ignore_user_abort(true); set_time_limit(0); unlink(__FILE__); $file = '.3.php'; ...

  9. 性能测试学习之路 (一)认识jmeter(性能测试流程 && 性能测试通过标准 &&jmeter体系结构)

    性能测试是通过自动化的测试工具模拟多种正常.峰值以及异常负载条件来对系统的各项性能指标进行测试. 1 性能测试技能树 性能测试是一项综合性的工作,致力于暴露性能问题,评估系统性能趋势.性能测试工作实质 ...

  10. Scrum 冲刺 第七篇

    Scrum 冲刺 第七篇 每日会议照片 昨天已完成工作 队员 昨日完成任务 黄梓浩 初步完成app首页模块的搭建 黄清山 完成部分个人界面模块数据库的接口 邓富荣 完成部分个人界面接口 钟俊豪 完成部 ...