文章目录
NullPointer异常:
错误描述:当试图访问一个空引用对象的属性或调用空引用对象的方法时,会抛出NullPointer异常。
复现示例:
String str = null; System.out.println(str.length());
解决方案:在使用对象之前,确保对象不为null。可以通过添加null检查或使用条件语句来避免该错误。
if (str != null) { System.out.println(str.length()); }
类型转换异常(ClassCastException):
错误描述:当试图将一个对象强制转换为与其实际类型不兼容的类型时,会抛出ClassCastException异常。
复现示例:
Object obj = "Java"; Integer num = (Integer) obj;
解决方案:在进行类型转换前,先使用instanceof运算符进行类型检查,确保对象可以成功转换。或者使用合适的类型转换操作来避免该错误。
if (obj instanceof Integer) { Integer num = (Integer) obj; // 进一步处理 }
数组越界异常(ArrayIndexOutOfBoundsException):
错误描述:当试图访问数组中超出有效索引范围的位置时,会抛出ArrayIndexOutOfBoundsException异常。
复现示例:
int[] arr = {1, 2, 3}; int element = arr[3];
解决方案:确保访问数组时,索引值在有效范围内。要注意Java数组的索引从0开始,因此最大索引是数组长度减1。
if (index >= 0 && index < arr.length) { int element = arr[index]; // 进一步处理 }
除零异常(ArithmeticException):
错误描述:当进行整数除法或取模运算时,除数为零会抛出ArithmeticException异常。
复现示例:
int a = 5; int b = 0; int result = a / b;
解决方案:在进行除法或取模运算时,要确保除数不为零,可以使用条件语句预先检查除数是否为零。
if (b != 0) { int result = a / b; // 进一步处理 }
输入输出异常(IOException):
错误描述:在处理输入输出操作时,如果出现读取或写入失败、文件不存在或无法访问等情况,会抛出IOException异常。
复现示例:
FileReader reader = new FileReader("path/to/nonexistent-file.txt"); int data = reader.read();
解决方案:在进行输入输出操作时,要确保文件存在、路径正确、权限足够,并且进行异常处理,例如使用try-catch块捕获和处理IOException异常。
try { FileReader reader = new FileReader("path/to/existing-file.txt"); int data = reader.read(); // 进一步处理 } catch (IOException e) { e.printStackTrace(); }
类未找到异常(ClassNotFoundException):
错误描述:当试图加载某个类,但找不到该类时,会抛出ClassNotFoundException异常。
复现示例:
try { Class.forName("com.example.NonExistentClass"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
解决方案:确保引用的类存在于正确的位置,并且类路径设置正确。如果使用外部库或框架,确保将相关的jar文件添加到类路径中。
并发修改异常(ConcurrentModificationException):
错误描述:当在进行迭代操作时,试图并发修改集合(如ArrayList)的结构时,会抛出ConcurrentModificationException异常。
复现示例:
List list = new ArrayList<>(); list.add("Java"); for (String item : list) { if (item.equals("Java")) { list.remove(item); } }
解决方案:避免在迭代时修改集合的结构。可以使用Iterator进行迭代,并使用Iterator的remove()方法删除元素,或者创建一个临时副本进行修改操作。
List list = new ArrayList<>(); list.add("Java"); Iterator iterator = list.iterator(); while (iterator.hasNext()) { String item = iterator.next(); if (item.equals("Java")) { iterator.remove(); } }
栈溢出错误(StackOverflowError):
错误描述:当方法调用的嵌套层级过深,导致栈空间耗尽时,会抛出StackOverflowError错误。
复现示例:
public static void recursiveMethod() { recursiveMethod(); } public static void main(String[] args) { recursiveMethod(); }
解决方案:确保递归方法具有退出条件,避免无限递归调用。每次递归调用时,问题规模应该减小,直到达到退出条件。
public static void recursiveMethod(int n) { if (n <= 0) { return; } // 进行递归操作 recursiveMethod(n - 1); }
类型不匹配异常(MismatchedInputException):
错误描述:在使用JSON库(如Jackson)反序列化时,如果JSON数据与目标类型不匹配,会抛出MismatchedInputException异常。
复现示例:
ObjectMapper mapper = new ObjectMapper(); String json = "{\"username\": \"Alice\", \"age\": 25}"; MyPojo pojo = mapper.readValue(json, MyPojo.class);
解决方案:确保JSON数据与目标类型匹配,包括字段名称和数据类型。可以使用@JsonProperty注解或自定义反序列化器来处理不匹配的字段。
public class MyPojo { @JsonProperty("username") private String username; // 其他字段和getter/setter }
时间格式化异常(DateTimeParseException):
错误描述:当尝试将字符串解析为日期或时间时,如果字符串格式与指定的格式不匹配,会抛出DateTimeParseException异常。
复现示例:
String dateStr = "2023-07-20"; LocalDate date = LocalDate.parse(dateStr);
解决方案:确保提供的字符串符合指定的日期或时间格式。可以使用DateTimeFormatter指定解析格式,并使用try-catch块来捕获并处理解析异常。
String dateStr = "2023-07-20"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); try { LocalDate date = LocalDate.parse(dateStr, formatter); // 进一步处理 } catch (DateTimeParseException e) { e.printStackTrace(); }
数字格式化异常(NumberFormatException):
错误描述:当尝试将一个无法转换为数字的字符串转换为数字类型时,会抛出NumberFormatException异常。
复现示例:
String numberStr = "ABC123"; int number = Integer.parseInt(numberStr);
解决方案:在进行字符串转换为数字的操作之前,确保字符串仅包含有效的数字字符。可以使用正则表达式或合适的校验方法来验证字符串是否为有效的数字。
String numberStr = "123"; if (numberStr.matches("\\d+")) { int number = Integer.parseInt(numberStr); // 进一步处理 }
僵尸对象(Memory Leak):
错误描述:当对象无法被垃圾回收机制回收,长时间驻留在内存中,导致内存泄漏时,会出现性能下降甚至内存溢出等问题。
复现示例:
public static List list = new ArrayList<>(); public static void main(String[] args) { while (true) { Object obj = new Object(); list.add(obj); } }
解决方案:确保不再使用的对象能够被垃圾回收机制回收。例如,在不需要的对象引用处做适当的释放或置为null,避免长时间持有对象的引用。
public static List list = new ArrayList<>(); public static void main(String[] args) { while (true) { Object obj = new Object(); list.add(obj); obj = null; // 释放对象引用 } }
方法重载冲突(AmbiguousMethodCallException):
错误描述:当调用一个方法时,传递的参数类型不明确,无法确定要调用哪个重载方法时,会抛出AmbiguousMethodCallException异常。
复现示例:
public static void printData(int data) { System.out.println("int: " + data); } public static void printData(double data) { System.out.println("double: " + data); } public static void main(String[] args) { printData(10); }
解决方案:在调用方法时,提供明确的参数类型,以消除重载方法的歧义。可以通过类型转换或者使用合适的参数类型来解决冲突。
public static void main(String[] args) { printData((double) 10); // 或者 printData(10.0); }
并发访问共享资源异常(ConcurrentModificationException):
错误描述:当多个线程同时访问和修改共享资源(如集合)时,可能会引发并发修改异常。
复现示例:
List list = new ArrayList<>(); list.add(1); list.add(2); Thread thread1 = new Thread(() -> { for (Integer num : list) { System.out.println(num); list.add(3); } }); Thread thread2 = new Thread(() -> { list.remove(0); }); thread1.start(); thread2.start();
解决方案:在多线程环境下,对于共享资源,应使用线程安全的数据结构或采用同步机制,如使用synchronized关键字或使用ConcurrentHashMap等线程安全集合类来保证并发访问的安全性。
类型参数推断错误(GenericParameterMismatchException):
错误描述:在使用泛型时,类型参数推断出现错误,导致无法正确匹配参数类型,从而引发类型参数不匹配异常。
复现示例:
List numbers = Arrays.asList(1, 2, 3, 4, 5); double average = numbers.stream() .mapToDouble(Double::valueOf) .average() .orElse(0);
解决方案:确保在使用泛型时,参数类型匹配。在上述示例中,应显式使用mapToDouble(Integer::doubleValue)来确保将Integer类型转换为Double类型。
方法签名冲突(DuplicateMethodException):
错误描述:在同一个类中定义了多个方法,它们的方法签名(包括方法名称、参数列表和返回类型)完全相同,导致方法签名冲突异常。
复现示例:
public class MathUtil { public int add(int a, int b) { return a + b; } public double add(int a, int b) { return (double) a + b; } }
解决方案:确保在同一个类中定义的方法具有不同的方法签名。可以通过修改方法名称、参数列表或返回类型来解决方法签名冲突。
空指针异常(NullPointerException):
错误描述:当尝试在一个空引用上调用方法、访问成员变量或数组时,会抛出空指针异常。
复现示例:
String str = null; int length = str.length();
解决方案:在使用对象之前,先进行空引用检查,确保对象不为null。可以使用条件判断、空引用时的默认值或者使用Optional类来处理潜在的空引用异常。
类型转换异常(ClassCastException):
错误描述:当试图将一个对象强制转换为不兼容的类型时,会抛出类型转换异常。
复现示例:
Object obj = "Hello"; Integer number = (Integer) obj;
解决方案:在进行类型转换之前,先进行类型验证,确保对象的实际类型与转换的目标类型兼容。可以使用instanceof操作符来检查类型,并使用合适的类型转换方式。
方法未找到异常(NoSuchMethodException):
错误描述:当通过反射或动态代理调用一个不存在的方法时,会抛出方法未找到异常。
复现示例:
Class clazz = MyClass.class; Method method = clazz.getMethod("nonExistentMethod");
解决方案:在使用反射调用方法之前,确保所要调用的方法存在。可以使用getDeclaredMethod()方法获取方法对象,并在调用之前进行合适的校验。
死锁(Deadlock):
错误描述:在多线程环境中,当两个或多个线程彼此等待对方释放资源而无法继续执行时,就会发生死锁。
复现示例:
Object resource1 = new Object(); Object resource2 = new Object(); Thread thread1 = new Thread(() -> { synchronized (resource1) { System.out.println("Thread 1: Holding resource 1..."); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (resource2) { System.out.println("Thread 1: Holding resource 1 and resource 2..."); } } }); Thread thread2 = new Thread(() -> { synchronized (resource2) { System.out.println("Thread 2: Holding resource 2..."); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (resource1) { System.out.println("Thread 2: Holding resource 2 and resource 1..."); } } }); thread1.start(); thread2.start();
解决方案:避免死锁的发生,可以确保线程获取资源的顺序一致,或者使用Lock接口和ReentrantLock类提供的更加灵活的锁机制。
文件操作异常(IOException):
错误描述:在进行文件读写或操作时,如果发生I/O错误,比如文件找不到、权限不足等,会抛出IOException异常。
复现示例:
try { FileInputStream file = new FileInputStream("path/to/file.txt"); // 进行文件操作 } catch (IOException e) { e.printStackTrace(); }
解决方案:在进行文件操作时,应处理可能发生的异常。可以使用try-catch语句块捕获IOException异常,并根据具体情况进行错误处理,如打印错误信息、关闭资源或进行其他恢复操作。
数据库访问异常(SQLException):
错误描述:当与数据库进行交互时,如果执行SQL语句出错或与数据库连接发生问题,会抛出SQLException异常。
复现示例:
try { Connection conn = DriverManager.getConnection(url, username, password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM users"); // 处理结果集 } catch (SQLException e) { e.printStackTrace(); }
解决方案:在进行数据库操作时,应注意处理可能发生的SQLException异常。可以使用try-catch语句块捕获异常,并根据具体情况进行错误处理,如打印错误信息、关闭资源或进行事务回滚。
外部资源未关闭异常(ResourceNotClosedException):
错误描述:在使用外部资源(如文件、数据库连接、网络连接等)时,如果忘记关闭资源,会导致资源泄漏和性能问题。
复现示例:
try { FileWriter writer = new FileWriter("path/to/file.txt"); writer.write("Hello, world!"); } catch (IOException e) { e.printStackTrace(); }
解决方案:确保在使用完外部资源后,及时关闭资源。可以使用try-with-resources语句来自动关闭实现了AutoCloseable接口的资源,或者在finally块中手动关闭资源。
数组越界异常(ArrayIndexOutOfBoundsException):
错误描述:当试图访问数组中不存在的索引位置时,会抛出数组越界异常。
复现示例:
int[] numbers = {1, 2, 3}; int value = numbers[5];
解决方案:在访问数组元素之前,应确保所访问的索引在合法范围内,即大于等于0且小于数组长度。可以使用条件判断来避免数组越界异常的发生。
类型错误(TypeError):
错误描述:当尝试在不兼容的数据类型之间进行操作时,会抛出类型错误。
复现示例:
int number = 10; String str = "Hello"; int result = number + str; // 类型不兼容
解决方案:确保进行操作的数据类型是兼容的。如果需要将一个数据类型转换为另一个数据类型,可以使用强制类型转换或者相关的类型转换方法(如Integer.parseInt())。
方法重写错误(OverrideError):
错误描述:在子类中重写父类的方法时,方法签名不匹配,导致方法重写错误。
复现示例:
class Parent { public void printMessage() { System.out.println("Parent class"); } } class Child extends Parent { public void printMsg() { System.out.println("Child class"); } }
解决方案:在子类中重写父类方法时,确保方法签名相同,即方法名称、参数列表和返回类型都相匹配。在上述示例中,应将printMsg()方法改为printMessage()。
线程同步错误(ThreadSynchronizationError):
错误描述:在多线程环境下,当多个线程访问共享资源且没有适当的同步机制时,会导致线程同步错误,如数据不一致、竞争条件等。
复现示例:
class Counter { private int count; public void increment() { count++; } public int getCount() { return count; } } public class Main { public static void main(String[] args) { Counter counter = new Counter(); for (int i = 0; i < 1000; i++) { new Thread(() -> counter.increment()).start(); } System.out.println("Count: " + counter.getCount()); } }
解决方案:在多线程环境下,确保对共享资源的访问是线程安全的。可以使用synchronized关键字、ReentrantLock类或Atomic类来进行线程同步操作,以避免竞争条件和数据不一致的问题。
类加载错误(ClassLoadingError):
错误描述:当尝试使用Class.forName()或类加载器加载类时,如果找不到或加载失败,会抛出类加载错误。
复现示例:
try { Class clazz = Class.forName("com.example.MyClass"); // 调用类的方法 } catch (ClassNotFoundException e) { e.printStackTrace(); }
解决方案:在使用Class.forName()或类加载器加载类之前,确保类的完整路径和名称是正确的,并且已经包含在类路径中。检查类路径和类名的拼写错误,以及确认所需的类文件是否存在。
连接超时异常(ConnectTimeoutException):
错误描述:在进行网络连接时,如果连接等待超过预设的超时时间仍未建立成功,会抛出连接超时异常。
复现示例:
try { URL url = new URL("http://www.example.com"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(5000); // 设置超时时间为5秒 // 进行网络请求 } catch (IOException e) { e.printStackTrace(); }
解决方案:在进行网络连接时,通过设置合适的超时时间来避免连接超时异常。可以使用setConnectTimeout()方法设置连接超时时间,确保在超时时间内成功建立连接,或者适当处理连接超时异常的情况。
内存溢出(OutOfMemoryError):
错误描述:当程序尝试使用更多的内存空间超过Java虚拟机所分配的最大内存限制时,会抛出内存溢出错误。
复现示例:
List numbers = new ArrayList<>(); while (true) { numbers.add(1); }
解决方案:避免内存溢出错误的发生,可以增加Java虚拟机的最大内存限制(通过-Xmx参数),优化程序的内存使用,及时释放无用的对象,减少对象的创建和拷贝等。
方法调用栈溢出(StackOverflowError):
错误描述:当方法调用的层级过深,超过了Java虚拟机所分配的栈空间时,会抛出方法调用栈溢出错误。
复现示例:
public class Main { public static void recursiveMethod() { recursiveMethod(); } public static void main(String[] args) { recursiveMethod(); } }
解决方案:避免方法调用栈溢出错误的发生,应检查方法递归调用的次数和深度,确保在合理范围内。如果需要进行大量递归操作,可以优化算法,使用尾递归或迭代来避免栈溢出。
并发修改异常(ConcurrentModificationException):
错误描述:在使用迭代器或集合的遍历过程中,如果尝试在遍历过程中修改集合结构(增加、删除元素),会抛出并发修改异常。
复现示例:
List list = new ArrayList<>(); list.add("Apple"); list.add("Banana"); for (String fruit : list) { if (fruit.equals("Apple")) { list.remove(fruit); // 并发修改异常 } }
解决方案:在使用迭代器或集合遍历时,不要在遍历过程中修改集合结构。可以使用迭代器的remove()方法来删除元素,或者在遍历时将需要删除的元素记录下来,在遍历结束后执行删除操作。
正则表达式错误(PatternSyntaxException):
错误描述:当使用不正确的正则表达式时,会抛出正则表达式错误。
复现示例:
String pattern = "["; Pattern.compile(pattern); // 正则表达式错误
解决方案:在使用正则表达式时,需要确保正则表达式的语法是正确的。可以使用try-catch块来捕获PatternSyntaxException异常,并检查错误消息以找到并修复正则表达式错误。
方法参数错误(IllegalArgumentException):
错误描述:当传递给方法的参数不符合方法要求时,会抛出非法参数异常。
复现示例:
public void processAge(int age) { if (age < 0) { throw new IllegalArgumentException("Age cannot be negative"); } // 其他处理 } public static void main(String[] args) { int age = -10; processAge(age); // 非法参数异常 }
解决方案:在编写方法时,清楚定义方法的参数要求,并进行必要的参数验证。在接收到非法参数时,可以抛出IllegalArgumentException异常,并提供相应的错误消息。
数字格式化异常(NumberFormatException):
错误描述:当字符串无法转换为有效的数字格式时,会抛出数字格式化异常。
复现示例:
String numberString = "abc"; int number = Integer.parseInt(numberString); // 数字格式化异常
解决方案:在将字符串转换为数字格式之前,应确保字符串具有有效的数字格式。可以使用try-catch块捕获NumberFormatException异常,并在出现异常时进行适当的处理或提供错误提示。
空指针异常(NullPointerException):
错误描述:当尝试在空对象上访问其成员或调用其方法时,会抛出空指针异常。
复现示例:
String str = null; int length = str.length(); // 空指针异常
解决方案:在使用对象之前,应确保对象不为空。可以使用条件判断或可空性检查来避免空指针异常的发生。另外,需要注意在使用"自动拆箱"和"自动装箱"时可能引发的空指针异常。
方法重载错误(OverloadError):
错误描述:当重载的方法在参数类型和数量上无法唯一确定调用方法时,会引起方法重载错误。
复现示例:
class Calculator { public void add(int a, int b) { System.out.println(a + b); } public void add(double a, double b) { System.out.println(a + b); } } public class Main { public static void main(String[] args) { Calculator calculator = new Calculator(); calculator.add(1, 2); // 方法重载错误 } }
解决方案:在进行方法重载时,确保重载方法在参数类型和数量上具有明确的区别,以便可以在调用时唯一确定要执行的方法。可以通过改变参数类型、参数数量或参数顺序来解决方法重载错误。
系统资源耗尽异常(OutOfSystemResourcesError):
错误描述:当系统资源(如文件句柄、线程、内存等)耗尽时,会抛出系统资源耗尽异常。
复现示例:
try { for (int i = 0; i < Integer.MAX_VALUE; i++) { new Thread(() -> { // 执行耗时操作 }).start(); } } catch (OutOfMemoryError e) { e.printStackTrace(); }
解决方案:合理管理和释放系统资源,以避免出现系统资源耗尽异常。尽量使用完资源后手动关闭或释放资源,并且避免浪费资源的操作。
方法返回值错误(ReturnValueError):
错误描述:在方法声明中指定了返回值类型,但方法可能没有返回值或返回了错误的类型。
复现示例:
public int divide(int a, int b) { if (b != 0) { return a / b; } }
解决方案:确保方法按照声明中指定的返回值类型返回正确的值。如果方法没有返回值,可以使用void关键字表示。如果方法返回类型为非基本类型(如对象或集合),确保返回的是正确的类型对象。
文件操作错误(FileOperationError):
错误描述:在进行文件操作时,如读取、写入、删除文件等操作,如果文件不存在、权限不足或文件被占用等情况,会抛出文件操作错误。
复现示例:
File file = new File("path/to/file.txt"); file.delete(); // 文件操作错误
解决方案:在进行文件操作之前,需要确保文件存在、具有足够的权限,并且没有被其他进程占用。可以使用条件判断来检查文件的存在性和可用性,并采取适当的错误处理操作。另外,需要在文件操作结束后及时释放文件资源。