Java基础中常见的陷阱
发布人:shili8
发布时间:2025-01-12 15:15
阅读次数:0
**Java 基础中的常见陷阱**
作为一名 Java 开发者,了解语言的基本特性和陷阱至关重要。以下是 Java 基础中一些常见的陷阱:
###1. null 指针异常null 指针异常是 Java 中最常见的错误之一。当你试图访问一个 null 对象的属性或方法时,会抛出 NullPointerException。
**示例代码**
javapublic class NullPointerExample { public static void main(String[] args) { String str = null; System.out.println(str.length()); // NullPointerException } }
**解决方案**
* 在使用对象之前检查其是否为 null。
* 使用 Optional 类来避免 null 指针异常。
###2. 异常处理Java 中的异常处理是非常重要的。然而,很多开发者忽略了这一点,导致程序崩溃或产生错误信息。
**示例代码**
javapublic class ExceptionExample { public static void main(String[] args) { try { int x =1 /0; } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
**解决方案**
* 使用 try-catch 块来捕获异常。
* 根据具体情况使用特定的异常类型(如 IOException、SQLException 等)。
* 保证在 finally 块中释放资源。
###3. 并发访问共享资源Java 中的并发编程是非常复杂的。多线程访问共享资源可能导致数据不一致或其他问题。
**示例代码**
javapublic class ConcurrencyExample { private static int count =0; public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { for (int i =0; i < 10000; i++) { count++; } }); Thread thread2 = new Thread(() -> { for (int i =0; i < 10000; i++) { count--; } }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(count); // 可能不为0 } }
**解决方案**
* 使用 synchronized 关键字来保护共享资源。
* 使用 Lock 类来实现更细粒度的锁定。
* 使用原子类(如 AtomicInteger)来避免并发访问问题。
###4. 内存泄漏Java 中的内存泄漏是指程序占用越来越多的内存,但没有释放。这种情况可能导致性能下降或甚至崩溃。
**示例代码**
javapublic class MemoryLeakExample { public static void main(String[] args) { while (true) { byte[] bytes = new byte[1024 *1024]; //1MB System.out.println(bytes); bytes = null; } } }
**解决方案**
* 使用 try-finally 块来确保资源释放。
* 使用 WeakReference 类来避免内存泄漏。
###5. 死锁Java 中的死锁是指两个或多个线程都在等待对方释放资源,从而导致程序崩溃。
**示例代码**
javapublic class DeadlockExample { public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Object lock2 = new Object(); Thread thread1 = new Thread(() -> { synchronized (lock1) { System.out.println("Thread1: Holding lock1"); try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } synchronized (lock2) { System.out.println("Thread1: Holding both locks"); } } }); Thread thread2 = new Thread(() -> { synchronized (lock2) { System.out.println("Thread2: Holding lock2"); try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } synchronized (lock1) { System.out.println("Thread2: Holding both locks"); } } }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); } }
**解决方案**
* 使用 synchronized 关键字来保护共享资源。
* 使用 Lock 类来实现更细粒度的锁定。
###6. 并发访问集合Java 中的并发访问集合是非常复杂的。多线程访问集合可能导致数据不一致或其他问题。
**示例代码**
javapublic class ConcurrentCollectionExample { private static Listlist = new ArrayList<>(); public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { for (int i =0; i < 10000; i++) { list.add("Thread1"); } }); Thread thread2 = new Thread(() -> { for (int i =0; i < 10000; i++) { list.remove(0); } }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(list.size()); // 可能不为0 } }
**解决方案**
* 使用 CopyOnWriteArrayList 类来避免并发访问问题。
* 使用 ConcurrentHashMap 类来避免并发访问问题。
###7. 并发访问MapJava 中的并发访问 Map 是非常复杂的。多线程访问 Map 可能导致数据不一致或其他问题。
**示例代码**
javapublic class ConcurrentMapExample { private static ConcurrentHashMapmap = new ConcurrentHashMap<>(); public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { for (int i =0; i < 10000; i++) { map.put("Thread1",1); } }); Thread thread2 = new Thread(() -> { for (int i =0; i < 10000; i++) { map.remove("Thread1"); } }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(map.size()); // 可能不为0 } }
**解决方案**
* 使用 ConcurrentHashMap 类来避免并发访问问题。
* 使用 CopyOnWriteHashMap 类来避免并发访问问题。
###8. 并发访问SetJava 中的并发访问 Set 是非常复杂的。多线程访问 Set 可能导致数据不一致或其他问题。
**示例代码**
javapublic class ConcurrentSetExample { private static HashSetset = new HashSet<>(); public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { for (int i =0; i < 10000; i++) { set.add("Thread1"); } }); Thread thread2 = new Thread(() -> { for (int i =0; i < 10000; i++) { set.remove("Thread1"); } }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(set.size()); // 可能不为0 } }
**解决方案**
* 使用 CopyOnWriteArraySet 类来避免并发访问问题。
* 使用 ConcurrentHashMap 类来避免并发访问问题。
###9. 并发访问QueueJava 中的并发访问 Queue 是非常复杂的。多线程访问 Queue 可能导致数据不一致或其他问题。
**示例代码**
javapublic class ConcurrentQueueExample { private static LinkedListqueue = new LinkedList<>(); public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { for (int i =0; i < 10000; i++) { queue.add("Thread1"); } }); Thread thread2 = new Thread(() -> { for (int i =0; i < 10000; i++) { queue.remove(0); } }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(queue.size()); // 可能不为0 } }
**解决方案**
* 使用 CopyOnWriteArrayQueue 类来避免并发访问问题。
* 使用 ConcurrentHashMap 类来避免并发访问问题。
###10. 并发访问DequeJava 中的并发访问 Deque 是非常复杂的。多线程访问 Deque 可能导致数据不一致或其他问题。
**示例代码**
javapublic class ConcurrentDequeExample { private static LinkedListdeque = new LinkedList<>(); public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread