7 Common Java String Pitfalls and How to Avoid Them
This article walks through frequent Java string‑related mistakes—including misuse of replace vs replaceAll, Integer equality pitfalls, BigDecimal precision issues, StringBuilder versus String, isEmpty vs isBlank, MyBatis mapper null checks, and indexOf logic—providing clear explanations, code examples, and best‑practice recommendations.
Preface
During a recent Sonar static analysis combined with manual code review, many code issues were discovered beyond typical bugs and security flaws, especially several confusing method usages that sparked my interest.
1. Does replace replace all characters?
When we want to replace characters like A with B in a string such as ATYSDFA*Y, the first thought is to use replace. To replace every A, replaceAll is more intuitive because its name suggests a global replacement.
The JDK documentation confirms that replace replaces each matching character, but it behaves differently from replaceAll.
Key differences: replace has two overloads: one takes char oldChar, char newChar for character replacement, and the other takes CharSequence target, CharSequence replacement for string replacement.
source.replace('A', 'B') source.replace("A", "B") replaceAlltakes a regular‑expression pattern and a replacement string, e.g. source.replaceAll("A", "B") For special characters like *, you can use: source.replaceAll("\\*", "C") or simply source.replace("*", "C") but avoid double‑escaping, which prevents replacement.
To replace only the first occurrence, use replaceFirst:
source.replaceFirst("A", "B")2. Can Integer be compared with == ?
Comparing two new Integer(1) objects with == yields false because they are distinct objects. The Integer constructor does not use the internal cache (‑128 to 127). The cache is used by Integer.valueOf and valueOf on String values, which can return true for the same value.
Therefore, prefer equals for value comparison:
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println(a.equals(b)); // true3. Does BigDecimal avoid precision loss?
Creating BigDecimal with the double constructor can still lose precision, e.g. new BigDecimal(0.02) yields a long decimal representation. The JDK documentation warns that this constructor may produce unexpected results.
To preserve exact values, use BigDecimal.valueOf or the Double.toString approach:
BigDecimal a = BigDecimal.valueOf(0.02);
BigDecimal b = BigDecimal.valueOf(0.03);
System.out.println(b.subtract(a)); // 0.014. Should string concatenation use String ?
Because String is immutable, repeated concatenation creates many intermediate objects. StringBuilder (or StringBuffer) should be used for efficient mutable concatenation.
StringBuilder sb = new StringBuilder();
sb.append(a).append(b);
System.out.println(sb); StringBuilderis not synchronized, making it faster than StringBuffer in single‑threaded scenarios. Since Java 5, the compiler optimizes the + operator on String to use StringBuilder under the hood.
5. Difference between isEmpty and isBlank
Various utility libraries provide these methods. isEmpty returns true only for null or "", while isBlank also treats strings containing only whitespace as empty.
StringUtils.isEmpty(null) // true
StringUtils.isEmpty("") // true
StringUtils.isEmpty(" ") // false
StringUtils.isBlank(null) // true
StringUtils.isBlank("") // true
StringUtils.isBlank(" ") // true6. Do MyBatis mapper results need null checks?
MyBatis’s DefaultResultSetHandler.handleResultSets always creates a non‑null List (named multipleResults), so the returned collection is never null. Therefore, explicit null checks before streaming are unnecessary.
List<User> list = userMapper.query(search);
List<Long> ids = list.stream().map(User::getId).collect(Collectors.toList());7. Correct usage of indexOf
indexOfreturns the position of the substring starting at 0, or -1 if not found. Checking > 0 misses matches at the beginning of the string.
String source = "#ATYSDFA*Y";
if (source.indexOf("#") > -1) {
System.out.println("do something");
}Alternatively, use contains for readability.
if (source.contains("#")) {
System.out.println("do something");
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Su San Talks Tech
Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
