零基础学Java第十六天之异常和错误的理解与解决

异常和错误的理解与解决

1、理解

异常是程序在运行期发生的****不正常的事件****,它会打断指令的正常执行流程。

设计良好的程序应该在异常发生时提供处理这些不正常事件的方法,使程序不会因为异常的发生而阻断或产生不可预见的结果。

Java语言使用异常处理机制为程序提供了****异常处理的能力****

2、分类

1、错误(Error)

JVM系统内部错误或资源耗尽等严重情况-****属于JVM需要负担的责任****这一类异常事件无法恢复或不可能捕获,将导致应用程序中断。

1、栈内存溢出的错误
package com.xx.exception01;

public class Test01 {
	/**
	 * Error出现的情况
	 * 
	 * 错误(Error):JVM系统内部错误或资源耗尽等严重情况-属于JVM需要负担的责
	 * 				任这一类异常事件无法恢复或不可能捕获,将导致应用程序中断。
	 */
	public static void main(String[] args) {
		
		//StackOverflowError - 栈内存溢出的错误
		method();
	}
	
	public static void method(){
		method();
	}
}

2、内存溢出的错误

package com.xx.exception01;

import java.util.ArrayList;

public class Test02 {
	/**
	 * Error出现的情况
	 * 
	 * 错误(Error):JVM系统内部错误或资源耗尽等严重情况-属于JVM需要负担的责
	 * 				任这一类异常事件无法恢复或不可能捕获,将导致应用程序中断。
	 */
	public static void main(String[] args) {
		//OutOfMemoryError - 内存溢出的错误
		//出现原因:创建出的数组对象的地址被集合存储,对象的空间就不会被释放,最终导致内存溢出
		ArrayList<byte[]> list = new ArrayList<>();
		while(true){
			byte[] bs = new byte[1024];
			list.add(bs);
		}
	}
	
}

2、异常(Exception)

其它因编程错误或偶然的外在因素导致的一般性问题。这类异常得到恰当的处理时,程序有机会恢复至正常运行状况。

1、类型转换异常:java.lang.ClassCastException
package com.xx.exception01;


public class Test05 {
	/**
	 * Exception出现的情况
	 * 
	 * 异常(Exception):其它因编程错误或偶然的外在因素导致的一般性问题。
	 * 					这类异常得到恰当的处理时,程序有机会恢复至正常运行状况。
	 * 
	 * RunntimeException - 运行时异常/非受检性异常:那些程序员在编写程序的时应该避免的异常(逻辑异常)
	 */
	public static void main(String[] args) {

		//ClassCastException - 类型转换异常
		Object obj = new Integer(100);
		Double d = (Double) obj;
		System.out.println(d);
	}
}
2、数组下标越界异常:java.lang.ArrayIndexOutOfBoundsException
1、理解
  1. 错误的索引值:当你使用一个超出数组长度(索引从0开始到数组长度减1)的整数作为索引来访问数组元素时,就会抛出这个异常。
  2. 循环中的错误:在循环中访问数组时,如果循环条件或索引更新逻辑不正确,就可能导致索引越界。
  3. 负索引:虽然这在正常的编程实践中很少见,但如果你不小心使用了负数作为数组索引,也会抛出异常。
  4. 动态计算索引时的错误:有时索引可能是通过某种计算动态得出的,如果计算逻辑有误,也可能导致索引越界。
2、解决方案
  • 检查并修正所有对数组索引的访问,确保索引值在有效范围内(0 到 array.length - 1)。
  • 在循环中,确保循环条件正确地限制了索引的范围。
  • 如果索引是动态计算的,请确保计算逻辑是正确的,并且结果始终在有效范围内。
  • 使用异常处理(try-catch 块)来捕获并处理可能的 ArrayIndexOutOfBoundsException,但这通常不是首选方法,因为更好的做法是避免异常的发生。
package com.qf.exception01;


public class Test06 {
	/**
	 * 知识点:Exception出现的情况
	 * 
	 * 异常(Exception):其它因编程错误或偶然的外在因素导致的一般性问题。
	 * 					这类异常得到恰当的处理时,程序有机会恢复至正常运行状况。
	 * 
	 * RunntimeException - 运行时异常/非受检性异常:那些程序员在编写程序的时应该避免的异常(逻辑异常)
	 */
	public static void main(String[] args) {
		
		//ArrayIndexOutOfBoundsException - 数组下标越界异常
		int[] arr = {1,2,3};
		System.out.println(arr[10]);
	}
}
3、空指针访问异常:java.lang.NullPointerException
1、理解
  1. 变量未初始化:当你声明了一个对象引用变量,但没有给它分配一个实际的对象时,它的默认值是null。如果此时你尝试使用这个变量去调用方法或访问字段,就会抛出空指针异常。
  2. 方法返回null:如果一个方法应该返回一个对象,但由于某种原因返回了null,而调用这个方法的代码没有检查这个返回值是否为null就直接使用,也会导致空指针异常。
  3. 数组或集合为空:当你尝试访问一个空数组或集合的元素时,虽然不会直接抛出NullPointerException,但如果你使用了错误的索引或键,可能会间接导致空指针异常,特别是当你使用索引或键来从一个对象(比如映射的值)中获取另一个对象时。
  4. 静态初始化中的错误:在静态初始化块或静态字段初始化时,如果引用了尚未初始化的对象,也可能导致空指针异常。
2、解决方案
  • 检查变量是否为null:在使用任何对象之前,确保它不是null
  • 对方法进行适当的错误处理:如果方法可能返回null,确保调用它的代码能够正确处理这种情况。
  • 避免空集合和数组:确保在访问集合或数组的元素之前,它们不是空的,或者使用了有效的索引或键。
  • 使用Java 8的Optional类:这是一个可以帮助你更好地处理可能为null的值的类。
  • 阅读并理解堆栈跟踪:当空指针异常发生时,Java会打印出一个堆栈跟踪,显示异常发生的位置。阅读并理解这个堆栈跟踪可以帮助你找到问题的根源。
package com.xx.exception01;

public class Test04 {

	public static void main(String[] args) {
		
		//NullPointerException - 空指针异常
		method(null);
	}
	
	public static void method(String str){
		System.out.println(str.length());
	}
	
}
4、算术异常(除0溢出):java.lang.ArithmeticException
package com.qf.exception01;


public class Test03 {
	/**
	 * RunntimeException - 运行时异常/非受检性异常:那些程序员在编写程序的时应该避免的异常(逻辑异常)
	 */
	public static void main(String[] args) {
		
		//ArithmeticException - 算数异常
		System.out.println(10/0);
		
	}
	
}
5、没有找到指定名称的类:java.lang.ClassNotFoundException
1、理解
  1. 类路径(Classpath)不正确:如果 JVM 没有在类路径中找到指定的类,则会抛出此异常。类路径是 JVM 用来查找类和资源的路径。
  2. 拼写或包名错误:类名或包名可能拼写错误,或者大小写不正确(Java 是大小写敏感的)。
  3. 编译时与运行时环境不一致:你可能在编译时使用了某个类,但在运行时环境中该类不存在。
  4. JAR 文件未包含:如果你的类在一个 JAR 文件中,但该 JAR 文件没有被添加到类路径中,也会导致这个异常。
  5. 动态加载类时出错:如果你使用 Class.forName() 或类加载器动态加载类,并且类不存在或路径错误,则会抛出此异常。
2、解决方法
  • 检查类路径:确保你的类在 JVM 的类路径中。你可以通过 -cp-classpath 参数来指定类路径,或者在 IDE(如 IntelliJ IDEA、Eclipse 等)中设置项目的类路径。
  • 检查拼写和包名:确保类名和包名都是正确的,并且大小写也匹配。
  • 清理和重建项目:如果你在使用 IDE,尝试清理并重建你的项目,以确保所有的类都正确编译和放置在正确的位置。
  • 检查 JAR 文件:如果你使用了 JAR 文件,确保它们被正确地添加到类路径中。
  • 检查动态加载代码:如果你在使用 Class.forName() 或类加载器动态加载类,请确保你传递的类名是完全限定的(包括包名),并且该类在类路径中可用。
  • 查看日志和异常堆栈跟踪:通常,当你遇到 ClassNotFoundException 时,JVM 会输出一个堆栈跟踪,显示是哪个类加载器在尝试加载类,以及是在哪里尝试加载的。这些信息可以帮助你定位问题。
6、访问不存在的文件:java.io.FileNotFoundException
1、理解
  1. 文件确实不存在:你尝试访问的文件在指定的路径下不存在。
  2. 文件路径错误:你提供的文件路径不正确或包含拼写错误。
  3. 文件路径指向目录:你尝试将目录作为文件来打开。
  4. 权限问题:虽然文件存在,但你的程序没有足够的权限去访问它。
  5. 磁盘空间不足:在某些情况下,如果磁盘空间不足,尝试创建新文件可能会失败,并抛出 FileNotFoundException(尽管这更常见的是抛出 IOException 或其他相关异常)。
  6. 文件被另一个进程锁定:在某些操作系统中,如果文件被另一个进程锁定或独占,则可能导致无法访问。
2、解决方案
  • 检查文件路径是否正确,并确保文件确实存在。
  • 确保你的程序有足够的权限去访问文件。
  • 捕获异常并优雅地处理它,例如通过向用户显示错误消息或尝试使用不同的文件路径。
7、操作文件时发送的异常:java.io.IOException
1、理解
  1. 文件不存在:尝试打开或读取一个不存在的文件。
  2. 文件路径错误:指定的文件路径不正确或无法访问。
  3. 权限问题:没有足够的权限来读取、写入或执行指定的文件。
  4. 磁盘空间不足:磁盘空间不足以完成操作。
  5. 磁盘错误:磁盘本身有问题,无法正确读写。
  6. 文件正在被其他程序使用:尝试打开或修改一个已被其他程序锁定或使用的文件。
  7. 文件系统错误:文件系统损坏或存在其他问题,导致无法正确访问文件。****
2、解决方案
  1. 捕获异常:在你的代码中,使用 try-catch 块来捕获可能抛出的 IOException
  2. 查看异常信息:通过 e.getMessage()e.printStackTrace() 获取异常的详细信息,这有助于确定问题的原因。
  3. 修复问题:根据异常信息,确定问题所在并修复它。例如,如果文件不存在,你可能需要检查文件路径是否正确,或者创建一个新文件。
  4. 测试:在修复问题后,重新运行你的代码以确保问题已解决。
8、操作数据库时发生的异常:java.sql.SQLException
1、理解

这个异常通常表示在尝试连接到数据库、执行查询、更新或关闭连接时发生了问题。

2、处理步骤
  1. 捕获异常:在你的代码中,使用 try-catch 块来捕获可能抛出的 SQLException
  2. 分析异常:在 catch 块中,你可以使用 e.getMessage() 来获取异常的详细信息,这有助于你确定问题的根源。
  3. 处理异常:根据异常的具体内容,你可以采取不同的修复措施。例如,如果是因为连接字符串不正确导致的异常,你需要检查并更新连接字符串。如果是因为表不存在或列名错误,你需要修正 SQL 语句。如果是因为权限问题,你需要检查数据库用户的权限设置。
  4. 资源清理:确保在 finally 块中关闭所有打开的数据库资源,如 Connection, Statement, ResultSet 等。这有助于避免资源泄漏和潜在的内存问题。
  5. 使用 try-with-resources:从 Java 7 开始,你可以使用 try-with-resources 语句来自动管理资源,它会在 try 代码块执行完毕后自动关闭资源。
  6. 查看文档和日志:如果问题仍然无法解决,查看数据库的文档和日志可能会提供有关问题的更多信息。
  7. 考虑使用数据库连接池:在生产环境中,使用数据库连接池(如 HikariCP, C3P0, Apache DBCP 等)可以提高性能和稳定性,并减少因频繁创建和关闭连接而导致的异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值