【Java】# Java易错知识点:replace、indexOf、数值包装类判断相等、数值精度问题、字符串拼接、字符串判空、mapper查询结果处理

【Java】# Java易错知识点:replace、indexOf、数值包装类判断相等、数值精度问题、字符串拼接、字符串判空、mapper查询结果处理,第1张

1. replace 与 replaceAll

场景:想要将 ABCABB 的 A 替换为 B

一看到这个场景,我们首先想到的就是用 replace方法(会替换几个 A 呢?)

如果将所有的 A 都替换为 B,可以使用 replaceAll 方法(这个没有争议)

问题:replace方法会替换几个 A 呢?

通过阅读源码,可以得知,replace方法会替换每一个匹配的字符串,那么它与 replaceAll 的区别在哪呢?

replace,拥有两个重载的方法

字符 的替换

public String replace(char oldChar, char newChar) {}

"ABCABB".replace('A', 'B');

字符串 的替换

public String replace(CharSequence target, CharSequence replacement) {}

"ABCABB".replace("A", "B");  // 注意,用的是字符串

replaceAll

基于正则表达式 的替换(也可以用于普通字符串的替换)

public String replaceAll(String regex, String replacement) {}

// 普通字符串的替换
"ABCABB".replaceAll("A", "B");

// 正则表达式替换
"AB$C$ABB".replaceAll("\$", "B");
// 如果想直接写 $,可以用 replace
"AB$C$ABB".replace("$", "B"); 

问题:如果只想替换第一个匹配的字符串呢? ----- replaceFirst()

"ABCABB".replaceFirst("A", "B")
2. indexOf 的使用

场景:如果字符串中包含 $ 字符,那么就打印出一句话

这个场景,我们可以使用两种方式进行解决,既然题目为 indexOf 的使用,那么先看如何用 indexOf 实现

if ("123dj9ABC".indexOf("$") > -1) {
    System.out.println("Hello world!")
}

一定要注意:if 语句中的条件,是 > -1,不能写为 > 0 (如果想要查找的 $字符在第一位,那么就会返回 0,则虽然包含 $,但是条件不成立)

问题:更简单的方法?(底层还是 indexOf) ------ contains()

if ("123dj9ABC".contains("$")) {
    System.out.println("Hello world!")
}

3. 数值包装类的相等问题

场景:判断两个 Integer 类型的数值是否相等

看到这个场景,如果代码中我们直接用 == 进行判断,结果是 true 还是 false呢

false 的结果 ----- new Integer(1);

Integer num1 = new Integer(1);
Integer num2 = new Integer(1);
System.out.println(num1 == num2); 

// 由于两个数是直接 new出来的,地址肯定不相同,所以直接使用 == ,返回 false

true 的结果 ----- Integer.valueOf(1);

Integer num1 = Integer.valueOf(1);
Integer num2 = Integer.valueOf(1);
System.out.println(num1 == num2);

// 通过阅读源码可以得知,使用 valueOf 方法时,数值在 -128 到 127范围内的值,是有缓存的,不会新 new一个

问题:涉及到数值类型的包装类如何进行相等判断?

解决:应使用 equals 方法进行判断

Integer num1 = new Integer(1);
Integer num2 = new Integer(1);
System.out.println(num1.equals(num2));   // 结果为  true

4. 数值精度问题

场景:交易金额进行计算

涉及到金额的计算,我们一般需要将字段类型定义为 BigDecimal,避免定义为 Double 类型时,精度丢失的问题

例如如下 *** 作:

double num1 = 0.03;
double num2 = 0.02;
System.out.println(num1 - num2);  // 使用 0.02 - 0.01 却不会损失精度

得到的结果是: 0.009999999999999998,与预计的 0.01 不相符

----> Double 类型的两个参数相减,会先将数字转为 二进制 再进行运算,而 Double的有效位数为 16位,所以可能会出现存储小数位数不够的情况,进而导致了误差的出现

问题:但是使用 BigDecimal 就一定能避免丢失精度嘛?

BigDecimal num1 = new BigDecimal(0.03);
BigDecimal num2 = new BigDecimal(0.02);
System.out.println(num1.subtract(num2));

得到的结果是:0.0099999999999999984734433411404097569175064563751220703125

通过阅读源码可知,构造方法的结果是不可预测的,例如想创建 0.1 的值,结果却是0.1000000000000000055511151231257827021181583404541015625的情况

解决:因此官方更推荐我们使用 valueOf 的方式

BigDecimal num1 = BigDecimal.valueOf(0.03);
BigDecimal num2 = BigDecimal.valueOf(0.02);
System.out.println(num1.subtract(num2));

如果在 IDEA上安装了 Alibaba的代码检查插件,也可以看到对应提示

5. 字符串拼接问题

场景:将两个字符串的值进行拼接

也许我们第一时间想到的就是用 “123” + “456” 的方式

但是 String 类型的字符串被称为不可变序列,也就是定义好之后,就不能被修改了(我们进行的修改,实际上是创建了新的对象)

可以看到底层使用的是 final 修饰的

问题:如何进行字符串的拼接呢?

使用可变字符序列 StringBuilder 和 StringBuffer,来定义对象

StringBuilder(线程不安全,效率高)StringBuffer(线程安全,效率低)
String a = "123";
StringBuilder builder = new StringBuilder();
builder.append(a).append("456");
System.out.println(builder);

问题:使用 + 拼接 String 类型的对象,效率一定比使用 append 拼接 StringBuilder 类型的对象低嘛?

public class StringDemo {
	public static void main(String[] args) {
		String a = "123";
		String b = "456";
		String c = a + b;
		System.out.println(c);
	}
}

通过使用 javap -c StringDemo.class,可以发现,虽然代码中用的是 + *** 作,但是编译为字节码文件之后,实际上是被优化为了 StringBuilder 的 append *** 作(JDK1.5之后)

6. 字符串判空问题

场景:判断前台传过来的字段值是否为空

我们一般常规的写法:

if (null != str && !"".equals(str)) {
    System.out.println("not empty");
}

每次都这么判断太不优雅了,可以使用主流的工具类

apache common 3中的 StringUtils

注意:isEmpty 和 isBlank 方法的区别

StringUtils.isEmpty(" ")        // false
StringUtils.isBlank(" ")        // true
7. mapper 查询结果的判空

场景:处理查询出来的结果

List<Student> list = studMapper.getList(params);
for (Student stu : list) {
    // todo
}

问题:这里是否要做判空处理,然后再进行 *** 作呢?

这里是不用进行判空的,通过阅读源码可知,MyBatis 的查询方法最终都会调用到 org.apache.ibatis.executor.resultset 包下的 DefaultResultSetHandler类的 handleResultSets方法,该方法会返回一个 multipleResultList 集合对象,而该对象在一开始就 new 出来了,肯定是不会空的,不会出现 NullPointerException

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1294767.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存