10 Java 17 Best Practices for Cleaner, Safer Code
This article presents ten practical Java 17 tips—ranging from using Optional and String.valueOf() to leveraging Arrays.copyOf, isEmpty(), pre‑compiled regex, and generics—to avoid common pitfalls, improve performance, and write more readable and robust backend code.
1. Nulls and Optionals
Bad example: Returning null from a method can cause a NullPointerException.
<code>public String getValue() {
// TODO
return null;
}</code>Good example: Use Optional to handle possible absence of a value explicitly.
<code>public Optional<String> getValue() {
// TODO
return Optional.empty();
}</code>2. Use String.valueOf() for String conversion
Bad example: Concatenating with the + operator performs implicit conversion and can be inefficient.
<code>double pi = 3.1415926;
String str = "" + pi;</code>Good example: Use the dedicated conversion method.
<code>double pi = 3.1415926;
String str = String.valueOf(pi);</code>3. Use Arrays.copyOf() to copy arrays
Bad example: Manually copying each element with a loop.
<code>int[] source = {1, 2, 3, 4, 5};
int[] target = new int[source.length];
for (int i = 0, len = source.length; i < len; i++) {
target[i] = source[i];
}</code>Good example: Delegate to the library method.
<code>int[] source = {1, 2, 3, 4, 5};
int[] target = Arrays.copyOf(source, source.length);</code>4. Use isEmpty() to check emptiness
Bad example: Checking length() for strings or size() for collections.
<code>String text = "Pack";
if (text.length() == 0) { /* ... */ }
Set<String> datas = new HashSet<>();
if (datas.size() == 0) { /* ... */ }</code>Good example: Use the constant‑time isEmpty() method.
<code>String text = "Pack";
if (text.isEmpty()) { /* ... */ }
Set<String> datas = new HashSet<>();
if (datas.isEmpty()) { /* ... */ }</code>5. Avoid ConcurrentModificationException
Bad example: Removing elements from a list while iterating with a foreach loop.
<code>List<String> datas = new ArrayList<>();
// add elements
for (String s : datas) {
if ("1".equals(s)) {
datas.remove(s);
}
}</code>Good example: Use an iterator’s remove() method or removeIf() .
<code>List<String> datas = new ArrayList<>();
Iterator<String> it = datas.iterator();
while (it.hasNext()) {
String value = it.next();
if ("1".equals(value)) {
it.remove();
}
}
// or
datas.removeIf(item -> "1".equals(item));</code>6. Pre‑compile regular expressions
Bad example: Compiling a pattern on each call with String.matches() .
<code>String str = "Hello, World";
if (str.matches("Hello.*")) {
System.out.println(true);
}</code>Good example: Compile once and reuse.
<code>private static final Pattern PATTERN1 = Pattern.compile("Hello.*");
public void validateString() {
String str = "Hello, World";
if (PATTERN1.matcher(str).matches()) {
System.out.println(true);
}
}</code>7. Skip unnecessary existence checks before retrieval
Bad example: Checking containsKey before get on a map.
<code>if (params.containsKey("action")) {
String value = params.get("action");
// ...
}</code>Good example: Retrieve directly and test for null .
<code>String action = params.get("action");
if (action != null) {
// ...
}</code>8. Efficiently convert collections to arrays
Bad example: Pre‑allocating an array with the collection size.
<code>String[] ret = datas.toArray(new String[datas.size()]);</code>Good example: Pass an empty array; the method will allocate the correctly sized one.
<code>String[] ret = datas.toArray(new String[0]);</code>9. Use default methods in interfaces
Bad example: Adding a new method to an interface forces all implementations to change.
<code>public interface Logger {
void log(String message);
}
public class FileLogger implements Logger { /* ... */ }
public class ConsoleLogger implements Logger { /* ... */ }</code>Good example: Provide a default implementation.
<code>public interface Logger {
void log(String message);
default void logError(String error) {
// default handling
}
}</code>10. Adopt the modern Date/Time API
Bad example: Using the mutable java.util.Date class.
<code>Date birthday = new Date();</code>Good example: Use the immutable classes from java.time (Java 8+).
<code>LocalDate date = LocalDate.now();
LocalDateTime dateTime = LocalDateTime.now();</code>11. Use generics for type safety
Bad example: A raw List holding mixed types.
<code>List datas = new ArrayList();
datas.add(10);
datas.add("Hello");</code>Good example: Declare the element type.
<code>List<Integer> datas = new ArrayList<>();
datas.add(10);
// datas.add("Hello"); // compile‑time error
</code>Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.