环境:Java17
反例:从方法返回null可能会导致最可怕的NullPointerException或NPE。
public String getValue() { // TODO return null ;}
正例:使用Optional可以更明确地处理 null,避免出现此类错误。
public Optional<String> getValue() { // TODO return Optional.empty() ;}
反例:使用 + 运算符进行字符串连接。
double pi = 3.1415926 ;String str = "" + pi ;
正例:使用内置方法进行字符串连接。
double pi = 3.1415926 ;String str = String.valueOf(pi) ;
反例:手动复制数组
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] ;}
这种方法效率较低,尤其是对于大数组,因为它需要进行多次迭代和元素赋值。
正例:使用 Arrays.copyOf()复制数组
int[] source = {1, 2, 3, 4, 5} ;int[] target = Arrays.copyOf(source, source.length) ;
反例:使用 length() 或 size() 检查字符串或集合是否为空。
String text = "Pack" ;if (text.length() == 0) { // TODO}Set<String> datas = new HashSet<>() ;if (datas.size() == 0) { // TODO}
正例:使用 isEmpty() 检查字符串或集合是否为空。
String text = "Pack" ;if (text.isEmpty()) { // TODO}Set<String> datas = new HashSet<>() ;if (datas.isEmpty()) { // TODO}
反例:在遍历列表时从列表中删除元素会导致 ConcurrentModificationException 异常。
List<String> datas = new ArrayList<>() ;datas.add("1") ;datas.add("2") ;datas.add("3") ;for (String s : datas) { if ("1".equals(s)) { datas.remove(s) ; }}
输出结果
图片
正例:使用迭代器的 remove 方法或 removeIf() 方法
List<String> datas = new ArrayList<>() ;// add(x)Iterator<String> it = datas.iterator() ;while (it.hasNext()) { String value = it.next() ; if ("1".equals(value)) { it.remove() ; }}
你也可以使用 Java 8 中引入的 removeIf() 方法,根据给定条件删除元素。
List<String> datas = new ArrayList<>() ;// add(x)datas.removeIf(item -> "1".equals(item)) ;
该方法在内部使用迭代器并移除与条件匹配的元素。这是一种更简洁、可读性更强的方法。
反例:运行时编译正则表达式
String str = "Hello, World" ;if (str.matches("Hello.*")) { System.out.println(true) ;}
正例:预编译正则表达式
private static final Pattern PATTERN1 = Pattern.compile("Hello.*") ; public void validateString() { String str = "Hello, World" ; if (PATTERN1.matcher(str).matches()) { System.out.println(true) ; }}
通过预编译重复使用的正则表达式,并在需要时重复使用它,我们可以避免不必要的编译,并提高性能。
反例:先判断是否存在然后在获取数据
public static void process(Map<String, String> params) { if (params.containsKey("action")) { String value = params.get("action") ; // TODO }}
正例:直接获取值判断是否null
String action = params.get("action") ;if (action != null) { // TODO}
这种方法避免了多余的检查,使代码更简洁、更高效。
反例:
List<String> datas = new ArrayList<>() ;datas.add("1") ;datas.add("2") ;datas.add("3") ;String[] ret = datas.toArray(new String[datas.size()]) ;
在这种方法中,首先计算列表的大小,然后创建一个新数组。这可能会影响性能,尤其是对于大数据集。
正例:
List<String> datas = new ArrayList<>() ;// add(x)String[] ret = datas.toArray(new String[0]) ;
在这里,调用 toArray 时使用的是空数组(new String[0]),这种方法避免了计算列表大小的需要,并允许 toArray 方法在内部处理数组大小的调整,从而获得更好的性能和更简洁的代码。
反例:
public interface Logger { void log(String message) ;}public class FileLogger implements Logger { public void log(String message) { // TODO }}public class ConsoleLogger implements Logger { public void log(String message) { // TODO }}
如果需要在接口中添加 logError 等新方法,则必须修改所有实现类,这可能会导致代码维护问题和潜在错误。
正例:
public interface Logger { void log(String message) ; default void logError(String error) { // TODO }}
在这里,Logger接口定义了一个默认方法(logError),它提供了记录错误的默认实现。这样实现类无需修改即可自动继承该默认实现。
反例:使用传统的Date类
Date birthday = new Date() ;// TODO
这个类有很多问题,比如可变性和方法不够清晰;该类中的大部分方法,如 getYear()、getMonth() 和 getDay() 已被弃用。
正例:使用Date/Time API(Java 8 及以后版本)中的类
LocalDate date = LocalDate.now() ;LocalDateTime dateTime = LocalDateTime.now() ;// TODO
在这里,使用来自Date/Time API的LocalDate、LocalDateTime类;这两个类是不可变的,确保了线程的安全性,并为日期操作提供了清晰直观的方法。
反例:
List datas = new ArrayList() ;datas.add(10) ;datas.add("Hello") ;
不同的数据类型混杂在列表中,可能导致运行时出错。
正例:使用泛型可以确保类型安全,避免此类问题
List<Integer> datas = new ArrayList<>() ;datas.add(10) ;// 错误// datas.add("Hello"
本文链接:http://www.28at.com/showinfo-26-96757-0.htmlJava开发人员必须掌握的11种干净代码最佳实践
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 面试官问到分布式事务?这样回答就对了!
下一篇: 避免消息积压的终极指南:四个关键技巧