刚上手Java会踩的坑

1.  用==号比较的坑

Integer类型的两个参数使用==号比较是否相等,或者使用String类型的两个变量进行==比较,天真的认为他们是理所应当的。

其实==操作只适用于基本数据类型如int , byte, boolean, short, char, long, float, double这些基本数据类型。

其它的包装类型Integer, Byte, Boolean, Short, Character Long, Float, Double 这些是对基本数据类型的包装类型。我们做项目的时候,保存数据类型一般都使用Integer这类包装数据类型,因为它们的默认值为null,而不是基本数据类型例如int的默认值是0。使用包装数据类型不容易出错,与前端进行交互时也可以快速的定位错误(数据字段前端有没有发过来,而不会有默认值,直接就是null)。

像String,数组,类的实例对象或者基本数据类型的包装类这类进行比较是否相等要使用equals(),因为它们是引用类型的数据。

 

        Integer integer = new Integer(1);
        Integer integer1 = new Integer(1);
        System.out.println(integer1 == integer); // false
        System.out.println(integer1.equals(integer)); // true

 

Integer中不是有范围是:-128-127的缓存吗?为什么是false?它其实并没有用到缓存

那么缓存是在哪里用的?答案在valueOf方法中:

        String s1 = new String("1");
        String s2 = new String("1");
        System.out.println(Integer.valueOf(s1) == Integer.valueOf(s2)); // true

 

2.Object.equals()

equals方法的判断逻辑如下:

  1. 该方法先判断对象a和b的引用是否相等,如果相等则直接返回true。

  2. 如果引用不相等,则判断a是否为空,如果a为空则返回false。

  3. 如果a不为空,调用对象的equals方法进一步判断值是否相等。

 

3. BigDecimal

通常我们会把一些小数类型的字段(比如:金额),定义成BigDecimal,而不是Double,避免丢失精度问题。

a - b应该等于0.01

        double a = 0.03;
        double b = 0.02;
        System.out.println(a - b);// 0.009999999999999998

Double类型的两个参数相减会转换成二进制,因为Double有效位数为16位这就会出现存储小数位数不够的情况,这种情况下就会出现误差。

我们使用BigDecimal能避免丢失精度。但也有坑在里面,我们可以使用Double.toString方法,对double类型的小数进行转换,这样能保证精度不丢失。

使用BigDecimal.valueOf方法初始化BigDecimal类型参数,也能保证精度不丢失。

 BigDecimal c = new BigDecimal(0.02);
        BigDecimal d = new BigDecimal(0.03);
        System.out.println(d.subtract(c)); // 0.0099999999999999984734433411404097569175064563751220703125

        BigDecimal r = new BigDecimal(Double.toString(0.02));
        BigDecimal g = new BigDecimal(Double.toString(0.03));
        System.out.println(g.subtract(r));// 0.01

        BigDecimal v = BigDecimal.valueOf(0.02);
        BigDecimal b = BigDecimal.valueOf(0.03);
        System.out.println(b.subtract(v));

 

4.  Java8 filter

Java8中的Stream用法很强大,刚使用时很震撼。对集合Stream操作,可以实现:遍历集合、过滤数据、排序、判断、转换集合等等功能。

public List<User> filterUser(List<User> userList) {
    if(CollectionUtils.isEmpty(userList)) {
        return Collections.emptyList();
    }
    
    return userList.stream()
    .filter(user -> user.getId() > 1000 && user.getAge() > 18)
    .collect(Collectors.toList());
}

如果你对过滤后的数据做修改将同时影响原本的数据

List<User> userList = queryUser();
List<User> filterList = filterUser(userList);
for(User user: filterList) {
   user.setName(user.getName() + "测试");
}

for(User user: userList) {
   System.out.println(user.getName());
}

其根本原因是:过滤后的集合中,保存的是对象的引用,该引用只有一份数据。

也就是说,只要有一个地方,把该引用对象的成员变量的值,做修改了,其他地方也会同步修改。

 

5. 自动拆箱

Java5之后,提供了自动装箱自动拆箱的功能。

自动装箱是指:JDK会把基本类型,自动变成包装类型。

Integer integer = 66;
// 等同
Integer integer = new Integer(66);

而自动拆箱是指:JDK会把包装类型,自动转换成基本类型。

Integer integer = new Integer(9);
int num= integer + 1;
// 等同于
Integer integer = new Integer(9);
int num= integer.intValue() + 1;

我们在使用自动拆箱时,往往忘记了判空,导致出现NullPointerException异常。

 

6. 字符串的replace() 和 replaeAll()

我们在使用字符串时,想把字符串中一些指定的字符替换成我们希望的字符。

replace方法:

1) 其中一个方法的参数:char oldChar 和 char newChar,支持字符的替换。

source.replace('A', 'B')

2) 另一个方法的参数是:CharSequence target 和 CharSequence replacement,支持字符串的替换。

source.replace("A", "B")

 

replaceAll方法的参数是:String regex 和 String replacement,即基于正则表达式的替换。

普通字符串进行替换: source.replaceAll("A", "B")

使用正则表达替换(将数字替换成A):str.replaceAll("\\d", "A")

只想替换第一个匹配的字符串,使用replaceFirst()方法

 

 

  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值