Java常见易错代码50例
1、字符串比较错误
// 错误示例
if (str == "hello") { ... } // 使用==比较字符串
// 正确示例
if ("hello".equals(str)) { ... } // 使用equals()比较字符串内容
// 或者使用
if (Objects.equals(str, "hello")) { ... } // 避免NPE
2、可变集合并发修改
// 错误示例
List<String> list = new ArrayList<>();
for (String item : list) {
if (item.equals("remove")) {
list.remove(item); // 可能抛出ConcurrentModificationException
}
}
// 正确示例
// 方法1: 使用Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (it.next().equals("remove")) {
it.remove();
}
}
// 方法2: 使用removeIf (Java 8+)
list.removeIf(item -> item.equals("remove"));
3、日期计算错误
// 错误示例
Date date = new Date();
date.setDate(date.getDate() + 1); // 使用过时的方法
// 正确示例
LocalDate date = LocalDate.now();
date = date.plusDays(1); // 使用新的日期API
// 或者
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, 1);
4、资源未正确关闭
// 错误示例
FileInputStream fis = new FileInputStream("file.txt");
// 使用文件...
fis.close(); // 如果发生异常,可能无法关闭
// 正确示例
try (FileInputStream fis = new FileInputStream("file.txt")) {
// 使用文件...
} // 自动关闭资源
5、数据库连接泄漏
// 错误示例
public User getUser(Long id) {
Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user WHERE id = ?");
ps.setLong(1, id);
ResultSet rs = ps.executeQuery();
// 处理结果...
return user; // 连接未关闭
}
// 正确示例
public User getUser(Long id) {
try (Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user WHERE id = ?")) {
ps.setLong(1, id);
try (ResultSet rs = ps.executeQuery()) {
// 处理结果...
return user;
}
}
}
6、空指针判断不当
// 错误示例
public void processUser(User user) {
if (user.getName().equals("admin")) { ... } // 可能NPE
// 正确示例
public void processUser(User user) {
if (user != null && "admin".equals(user.getName())) { ... }
// 或使用Optional
Optional.ofNullable(user)
.map(User::getName)
.filter("admin"::equals)
.ifPresent(name -> { ... });
}
7、线程池配置不当
// 错误示例
ExecutorService executor = Executors.newFixedThreadPool(10); // 使用预定义的线程池
// 正确示例
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数
10, // 最大线程数
60L, // 空闲时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(100), // 工作队列
new ThreadFactoryBuilder().setNameFormat("worker-%d").build(), // 线程工厂
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
8、异常处理不当
// 错误示例
try {
// 业务代码
} catch (Exception e) {
e.printStackTrace(); // 不应该直接打印堆栈
// 或者
log.error(e.getMessage()); // 丢失堆栈信息
}
// 正确示例
try {
// 业务代码
} catch (Exception e) {
log.error("操作失败", e); // 记录完整异常信息
thrownew BusinessException("操作失败", e); // 转换为业务异常
}
9、HashMap的线程安全问题
// 错误示例
private Map<String, User> userCache = new HashMap<>(); // 多线程环境下不安全
// 正确示例
private Map<String, User> userCache = new ConcurrentHashMap<>();
// 或者
private Map<String, User> userCache = Collections.synchronizedMap(new HashMap<>());
10、金额计算精度问题
// 错误示例
double price = 9.99;
double quantity = 2.0;
double total = price * quantity; // 可能产生精度误差
// 正确示例
BigDecimal price = new BigDecimal("9.99");
BigDecimal quantity = new BigDecimal("2");
BigDecimal total = price.multiply(quantity);
11、集合初始化容量不合理
// 错误示例
List<User> users = new ArrayList<>(); // 默认容量10
for (int i = 0; i < 1000; i++) {
users.add(new User()); // 多次扩容
}
// 正确示例
List<User> users = new ArrayList<>(1000); // 预估容量
for (int i = 0; i < 1000; i++) {
users.add(new User());
}
12、忽略方法返回值
// 错误示例
String str = "hello,world";
str.replace('l', 'L'); // String是不可变的,结果被忽略
// 正确示例
String str = "hello,world";
str = str.replace('l', 'L'); // 保存替换后的结果
13、使用原始类型集合
// 错误示例
List list = new ArrayList(); // 原始类型
list.add("string");
list.add(123); // 可以添加任何类型
// 正确示例
List<String> list = new ArrayList<>(); // 使用泛型
list.add("string");
// list.add(123); // 编译错误
14、对象比较实现不当
// 错误示例
publicclass User {
private Long id;
private String name;
@Override
public boolean equals(Object obj) {
if (obj instanceof User) {
User other = (User) obj;
returnthis.id == other.id; // 使用==比较Long
}
returnfalse;
}
// 没有重写hashCode()
}
// 正确示例
publicclass User {
private Long id;
private String name;
@Override
public boolean equals(Object obj) {
if (this == obj) returntrue;
if (!(obj instanceof User)) returnfalse;
User other = (User) obj;
return Objects.equals(this.id, other.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
15、线程同步范围过大
// 错误示例
publicclass UserService {
public synchronized void processUser(User user) { // 整个方法同步
// 执行耗时操作...
}
}
// 正确示例
publicclass UserService {
public void processUser(User user) {
// 非同步代码
synchronized (this) { // 只同步关键部分
// 需要同步的代码
}
// 非同步代码
}
}
16、日期格式化线程安全问题
// 错误示例
publicclass DateUtil {
privatestaticfinal SimpleDateFormat sdf =
new SimpleDateFormat("yyyy-MM-dd"); // SimpleDateFormat非线程安全
public static String format(Date date) {
return sdf.format(date);
}
}
// 正确示例
publicclass DateUtil {
privatestaticfinal DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd"); // DateTimeFormatter是线程安全的
public static String format(LocalDate date) {
return formatter.format(date);
}
}
17、使用魔法数字
// 错误示例
if (status == 1) { // 魔法数字
// 处理激活状态
} elseif (status == 2) {
// 处理暂停状态
}
// 正确示例
publicenum UserStatus {
ACTIVE(1), SUSPENDED(2);
privatefinalint value;
UserStatus(int value) {
this.value = value;
}
}
if (status == UserStatus.ACTIVE.getValue()) {
// 处理激活状态
}
18、忽略中断异常
// 错误示例
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 空catch块,丢失中断状态
}
// 正确示例
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
throw new RuntimeException(e);
}
19、使用System.gc()
// 错误示例
System.gc(); // 企图强制垃圾回收
// 正确示例
// 让JVM自己决定何时进行GC
// 通过JVM参数调优垃圾回收
20、递归没有终止条件
// 错误示例
public void recursiveMethod(int n) {
recursiveMethod(n - 1); // 没有终止条件
}
// 正确示例
public void recursiveMethod(int n) {
if (n <= 0) { // 终止条件
return;
}
recursiveMethod(n - 1);
}
21、锁的粒度不当
// 错误示例
publicclass CacheService {
private Map<String, Object> cache = new ConcurrentHashMap<>();
privatefinal Object lock = new Object();
public void updateCache(String key, Object value) {
synchronized (lock) { // 锁粒度太大,影响所有key的更新
// 耗时的计算...
cache.put(key, value);
}
}
}
// 正确示例
publicclass CacheService {
private Map<String, Object> cache = new ConcurrentHashMap<>();
private Map<String, Object> lockMap = new ConcurrentHashMap<>();
public void updateCache(String key, Object value) {
Object keyLock = lockMap.computeIfAbsent(key, k -> new Object());
synchronized (keyLock) { // 对每个key单独加锁
// 耗时的计算...
cache.put(key, value);
}
}
}
22、集合遍历时判断null
// 错误示例
List<String> list = Arrays.asList("a", null, "b");
for (String str : list) {
if (str.length() > 0) { // 可能NPE
// ...
}
}
// 正确示例
List<String> list = Arrays.asList("a", null, "b");
for (String str : list) {
if (str != null && str.length() > 0) {
// ...
}
}
// 或使用Stream API的filter
list.stream()
.filter(Objects::nonNull)
.filter(str -> str.length() > 0)
.forEach(str -> {
// ...
});
23、过度创建对象
// 错误示例
publicclass StringUtils {
public static boolean isUpperCase(String str) {
return str.equals(str.toUpperCase()); // 每次都创建新字符串
}
}
// 正确示例
publicclass StringUtils {
public static boolean isUpperCase(String str) {
for (int i = 0; i < str.length(); i++) {
if (!Character.isUpperCase(str.charAt(i))) {
returnfalse;
}
}
returntrue;
}
}
24、忽略SQL注入风险
// 错误示例
public User findUser(String name) {
String sql = "SELECT * FROM user WHERE name = '" + name + "'"; // SQL注入风险
// 执行SQL...
}
// 正确示例
public User findUser(String name) {
String sql = "SELECT * FROM user WHERE name = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, name); // 使用参数化查询
// 执行SQL...
}
}
25、不恰当的单例实现
// 错误示例
publicclass Singleton {
privatestatic Singleton instance;
public static Singleton getInstance() {
if (instance == null) { // 非线程安全
instance = new Singleton();
}
return instance;
}
}
// 正确示例
publicclass Singleton {
private Singleton() {}
privatestaticclass Holder {
privatestaticfinal Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE; // 线程安全的延迟初始化
}
}
26、内存泄漏
// 错误示例
publicclass Cache {
privatestatic Map<String, Object> cache = new HashMap<>();
public static void put(String key, Object value) {
cache.put(key, value); // 缓存项永远不会被移除
}
}
// 正确示例
publicclass Cache {
privatestatic Map<String, Object> cache = new WeakHashMap<>(); // 使用WeakHashMap
// 或
privatestatic Cache INSTANCE = new Cache(1000); // 限制大小
privatefinal Map<String, Object> cache;
public Cache(int maxSize) {
this.cache = new LinkedHashMap<String, Object>(maxSize, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, Object> eldest) {
return size() > maxSize;
}
};
}
}
27、不恰当的异常捕获顺序
// 错误示例
try {
// 可能抛出异常的代码
} catch (Exception e) { // 捕获所有异常
// 处理异常
} catch (IOException e) { // 永远不会执行到这里
// 处理IO异常
}
// 正确示例
try {
// 可能抛出异常的代码
} catch (IOException e) { // 先捕获具体异常
// 处理IO异常
} catch (Exception e) { // 最后捕获通用异常
// 处理其他异常
}
28、忽略线程中断
// 错误示例
public void task() {
while (!Thread.interrupted()) { // 检查中断状态但清除了标志
// 执行任务
}
}
// 正确示例
public void task() {
while (!Thread.currentThread().isInterrupted()) { // 不清除中断状态
try {
// 执行任务
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
break;
}
}
}
29、随机数使用不当
// 错误示例
publicclass RandomUtil {
privatestatic Random random = new Random(); // 可能在多线程环境下有问题
public static int nextInt(int bound) {
return random.nextInt(bound);
}
}
// 正确示例
publicclass RandomUtil {
privatestaticfinal ThreadLocal<Random> random =
ThreadLocal.withInitial(Random::new);
public static int nextInt(int bound) {
return random.get().nextInt(bound);
}
}
30、对象克隆实现不当
// 错误示例
publicclass User implements Cloneable {
private List<Order> orders;
@Override
public User clone() {
try {
return (User) super.clone(); // 浅拷贝
} catch (CloneNotSupportedException e) {
thrownew RuntimeException(e);
}
}
}
// 正确示例
publicclass User implements Cloneable {
private List<Order> orders;
@Override
public User clone() {
try {
User clone = (User) super.clone();
clone.orders = new ArrayList<>(this.orders); // 深拷贝
return clone;
} catch (CloneNotSupportedException e) {
thrownew RuntimeException(e);
}
}
}
31、文件路径处理不当
// 错误示例
String path = baseDir + fileName; // 可能产生路径问题
// 正确示例
Path path = Paths.get(baseDir).resolve(fileName); // 使用Path API
// 或
File file = new File(baseDir, fileName);
32、缓冲区使用不当
// 错误示例
public void copyFile(String src, String dst) throws IOException {
try (FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst)) {
int c;
while ((c = in.read()) != -1) { // 一次读取一个字节
out.write(c);
}
}
}
// 正确示例
public void copyFile(String src, String dst) throws IOException {
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dst))) {
byte[] buffer = newbyte[8192];
int length;
while ((length = in.read(buffer)) != -1) { // 使用缓冲区
out.write(buffer, 0, length);
}
}
}
33、忽略字符编码
// 错误示例
String content = new String(bytes); // 使用平台默认编码
// 正确示例
String content = new String(bytes, StandardCharsets.UTF_8); // 指定编码
34、使用switch时忘记break
// 错误示例
switch (type) {
case1:
doSomething(); // 会继续执行下一个case
case2:
doSomethingElse();
}
// 正确示例
switch (type) {
case1:
doSomething();
break;
case2:
doSomethingElse();
break;
default:
thrownew IllegalArgumentException("Unknown type: " + type);
}
35、资源路径处理不当
// 错误示例
File file = new File("config.properties"); // 相对路径可能找不到文件
// 正确示例
InputStream is = getClass().getClassLoader()
.getResourceAsStream("config.properties"); // 使用类加载器加载资源
36、并发集合使用不当
// 错误示例
List<String> list = Collections.synchronizedList(new ArrayList<>());
synchronized (list) { // 不需要额外同步
Iterator<String> it = list.iterator();
while (it.hasNext()) {
// ...
}
}
// 正确示例
List<String> list = new CopyOnWriteArrayList<>(); // 使用并发安全的集合
for (String item : list) { // 迭代时不需要同步
// ...
}
37、数值溢出
// 错误示例
int result = Integer.MAX_VALUE + 1; // 溢出
// 正确示例
long result = (long) Integer.MAX_VALUE + 1; // 使用更大的数据类型
// 或使用Math类的方法检查
if (a > Integer.MAX_VALUE - b) {
throw new ArithmeticException("Integer overflow");
}
38、对象状态未检查
// 错误示例
publicclass Connection {
privateboolean closed;
public void send(String message) { // 未检查连接状态
// 发送消息
}
}
// 正确示例
publicclass Connection {
privatevolatileboolean closed;
public void send(String message) {
if (closed) {
thrownew IllegalStateException("Connection is closed");
}
// 发送消息
}
}
39、数组拷贝不当
// 错误示例
User[] users = getUsers();
User[] copy = new User[users.length];
System.arraycopy(users, 0, copy, 0, users.length); // 浅拷贝
// 正确示例
User[] users = getUsers();
User[] copy = new User[users.length];
for (int i = 0; i < users.length; i++) {
copy[i] = users[i].clone(); // 深拷贝
}
40、忽略线程池关闭
// 错误示例
class Service {
private ExecutorService executor = Executors.newFixedThreadPool(10);
// 服务关闭时未关闭线程池
}
// 正确示例
class Service implements AutoCloseable {
privatefinal ExecutorService executor = Executors.newFixedThreadPool(10);
@Override
public void close() {
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
41、忽略时区问题
// 错误示例
Date date = new Date(); // 使用系统默认时区
// 正确示例
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
// 或
Instant now = Instant.now(); // 使用UTC时间
42、未使用finally释放资源
// 错误示例
Lock lock = new ReentrantLock();
lock.lock();
try {
// 处理逻辑
} catch (Exception e) {
// 异常处理
}
// 可能忘记释放锁
// 正确示例
Lock lock = new ReentrantLock();
lock.lock();
try {
// 处理逻辑
} catch (Exception e) {
// 异常处理
} finally {
lock.unlock(); // 确保释放锁
}
43、使用可变对象作为Map键
// 错误示例
Map<List<String>, String> map = new HashMap<>();
List<String> key = new ArrayList<>();
key.add("a");
map.put(key, "value");
key.add("b"); // 改变key的状态
// map.get(key) 可能返回null
// 正确示例
Map<List<String>, String> map = new HashMap<>();
List<String> key = List.of("a", "b"); // 使用不可变List
map.put(key, "value");
44、忽略线程安全的日期处理
// 错误示例
privatestaticfinal SimpleDateFormat sdf =
new SimpleDateFormat("yyyy-MM-dd"); // 非线程安全
// 正确示例
privatestaticfinal DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 线程安全
// 或使用ThreadLocal
privatestaticfinal ThreadLocal<SimpleDateFormat> dateFormat =
ThreadLocal.withInitial(() ->
new SimpleDateFormat("yyyy-MM-dd"));
45、错误的equals实现
// 错误示例
public boolean equals(User other) { // 参数类型错误
if (other == null) returnfalse;
returnthis.id == other.id;
}
// 正确示例
@Override
public boolean equals(Object obj) {
if (this == obj) returntrue;
if (!(obj instanceof User)) returnfalse;
User other = (User) obj;
return Objects.equals(this.id, other.id);
}
46、使用双重检查锁定而不使用volatile
// 错误示例
privatestatic Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton(); // 可能部分初始化
}
}
}
return instance;
}
// 正确示例
privatestaticvolatile Singleton instance; // 使用volatile
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
47、使用原始类型而不是泛型
// 错误示例
List list = new ArrayList();
list.add("string");
String str = (String) list.get(0); // 需要类型转换
// 正确示例
List<String> list = new ArrayList<>();
list.add("string");
String str = list.get(0); // 不需要类型转换
48、未正确实现序列化
// 错误示例
publicclass User implements Serializable {
private String name;
privatetransient String password; // 密码不序列化
// 没有serialVersionUID
}
// 正确示例
publicclass User implements Serializable {
privatestaticfinallong serialVersionUID = 1L;
private String name;
privatetransient String password;
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
// 自定义序列化逻辑
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
// 自定义反序列化逻辑
}
}
49、使用StringBuffer而不是StringBuilder
// 错误示例
StringBuffer buffer = new StringBuffer(); // 线程安全,但性能较差
// 正确示例
StringBuilder builder = new StringBuilder(); // 单线程使用
// 或在需要线程安全时使用StringBuffer
50、忽略Future的取消状态
// 错误示例
Future<?> future = executor.submit(task);
try {
future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
// 超时但未取消任务
}
// 正确示例
Future<?> future = executor.submit(task);
try {
future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true); // 取消任务
throw e;
} catch (CancellationException e) {
// 处理取消状态
}