【BUG日记】【JAVA】String.indexOf(x),字符串x的长度是0返回true!

简介: 【BUG日记】【JAVA】String.indexOf(x),字符串x的长度是0返回true!

【日期】


2022/4/11


【问题】


今天,在和前端同事A对接接口的时候,发现前端传入空字符串,也能存入状态。(这里是把状态弄成一个公共方法,判断一个字符串不在这些字符串里)


例如:判断data是否有txt


/**
   * 判断data是否有txt
   * 
   * @Method: isTxtInDate
   * @author: nanfangzhe
   * @date: 2022年4月11日
   * @param txt
   * @param data
   * @return boolean
   */
  public static boolean isTxtInDate(String txt, String data) {
    // return data.indexOf(txt) != -1;
  }


但是,这里是存在问题的,如果传入空的字符串:"",长度为0;返回结果也是true,就会导致出错了!


如图:


微信截图_20220520124525.png


【原因】


原因是:indexOf的源码里,字符串长度是0,会直接返回规则的Data数据的长度,而不是会返回-1;进而返回false。


if (fromIndex >= sourceCount) {
            return (targetCount == 0 ? sourceCount : -1);
        }


【如何发现】


查看String.indexOf的源码


我们也来了解和分析一下indexOf()的原理,探索底层原理


这里就直接把理解和分析写在注释上了。(这里是直接复制最底层的indexOf的方法)


static int indexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount, int fromIndex) {
        // fromIndex从第几个开始对比;匹配是,默认为0;
        // sourceCount是data(大的字符串)的长度
        if (fromIndex >= sourceCount) {  // 这里data的长度如果是0,就直接被返回了
            return (targetCount == 0 ? sourceCount : -1);  // targetCount也是data的长度,所以直接返回了0,而不是返回-1
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        if (targetCount == 0) {
            return fromIndex;
        }
        char first = target[targetOffset];
        int max = sourceOffset + (sourceCount - targetCount);
        for (int i = sourceOffset + fromIndex; i <= max; i++) {
            /* Look for first character. */
            if (source[i] != first) {
                while (++i <= max && source[i] != first);
            }
            /* Found first character, now look at the rest of v2 */
            if (i <= max) {
                int j = i + 1;
                int end = j + targetCount - 1;
                for (int k = targetOffset + 1; j < end && source[j]
                        == target[k]; j++, k++);
                if (j == end) {
                    /* Found whole string. */
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }


【如何修复】


底层逻辑了解清楚了,肯定不能改动了,我们就在封装的方法里修改。


  两种解决:① 控制先判断为空就返回false再加一个 data.indexOf(txt) != 0

这里选择第一种方法。最终选择,多加一个判断commons.lang3的

StringUtils.isBlank(txt).


修改后的代码如下:


public static boolean isTxtInDate(String txt, String data) {
    return StringUtils.isBlank(txt) == true ? false : data.indexOf(txt) != -1; // 如果txt为空,直接返回false(因为indexOf判断传入长度为0的字符串也会返回true)
  }


StringUtils.isBlank()方法,需要引入的pom文件


<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.12.0</version>
</dependency>


【完整代码分享】


package com.nanfangzhe.anpai;
import org.apache.commons.lang3.StringUtils;
public class Demo {
  public static void main(String[] args) {
    Integer status = 0;
    String textRule = "1,2,3";
    System.out.println("状态必须符合:" + textRule);
    System.out.println("status = 0:" + isTxtInDate(status.toString(), textRule) + "\n不继续往下执行");
    System.out.println("status = \"\":" + isTxtInDate("", textRule) + "\n继续往下执行");
  }
  /**
   * 判断data是否有txt
   * 
   * @Method: isTxtInDate
   * @author: nanfangzhe
   * @date: 2022年4月11日
   * @param txt
   * @param data
   * @return boolean
   */
  public static boolean isTxtInDate(String txt, String data) {
    return StringUtils.isBlank(txt) == true ? false : data.indexOf(txt) != -1; // 如果txt为空,直接返回false(因为indexOf判断传入长度为0的字符串也会返回true)
  }
}


【总结】


封装方法时要考察该底层方法,进行也要测试到位!


文章小尾巴


文章写作、模板、文章小尾巴可参考:《写作“小心思”》


  感谢你看到最后,最后再说两点~


  ①如果你持有不同的看法,欢迎你在文章下方进行留言、评论。

  ②如果对你有帮助,或者你认可的话,欢迎给个小点赞,支持一下~


  我是南方者,一个热爱计算机更热爱祖国的南方人。


  (文章内容仅供学习参考,如有侵权,非常抱歉,请立即联系作者删除。)



目录
相关文章
|
8天前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
21 0
java基础(13)String类
|
19天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
18天前
|
存储 安全 Java
Java——String类详解
String 是 Java 中的一个类,用于表示字符串,属于引用数据类型。字符串可以通过多种方式定义,如直接赋值、创建对象、传入 char 或 byte 类型数组。直接赋值会将字符串存储在串池中,复用相同的字符串以节省内存。String 类提供了丰富的方法,如比较(equals() 和 compareTo())、查找(charAt() 和 indexOf())、转换(valueOf() 和 format())、拆分(split())和截取(substring())。此外,还介绍了 StringBuilder 和 StringJoiner 类,前者用于高效拼接字符串,后者用于按指定格式拼接字符串
19 1
Java——String类详解
|
4天前
|
Java 数据库
java小工具util系列1:日期和字符串转换工具
java小工具util系列1:日期和字符串转换工具
12 3
|
4天前
|
SQL Java 索引
java小工具util系列2:字符串工具
java小工具util系列2:字符串工具
7 2
|
3天前
|
索引
Sass String(字符串) 函数
Sass String(字符串) 函数用于处理字符串并获取相关信息。
11 1
|
7天前
|
存储 移动开发 Java
java核心之字符串与编码
java核心之字符串与编码
13 2
|
15天前
|
安全 Java
Java StringBuffer 和 StringBuilder 类详解
在 Java 中,`StringBuffer` 和 `StringBuilder` 用于操作可变字符串,支持拼接、插入、删除等功能。两者的主要区别在于线程安全性和性能:`StringBuffer` 线程安全但较慢,适用于多线程环境;`StringBuilder` 非线程安全但更快,适合单线程环境。选择合适的类取决于具体的应用场景和性能需求。通常,在不需要线程安全的情况下,推荐使用 `StringBuilder` 以获得更好的性能。
|
15天前
|
Java 索引
Java String 类详解
Java 中的 `String` 类用于表示不可变的字符序列,是 Java 标准库 `java.lang` 包的一部分。字符串对象一旦创建,其内容不可更改,修改会生成新对象。
|
14天前
|
Java
Java实现:将带时区的时间字符串转换为LocalDateTime对象
通过上述方法,你可以将带时区的时间字符串准确地转换为 `LocalDateTime`对象,这对于处理不需要时区信息的日期和时间场景非常有用。
205 4
下一篇
无影云桌面