文章目录
cho1.
基本问题
- 什么是异常
Java中用于处理程序出错的一种机制。 - 学习重点
- 熟悉异常体系。
- 能够看懂日志信息,处理常见的几种异常。
- 可以编写自定义异常。
- 注意
- 这里存在两种异常的概念。一种是广义的,即程序出现的错误均称为异常;另一种是狭义的,即异常体系下,与error同级的exception。
cho2.
异常体系
- 异常体系的最顶层是Throwable接口。
- 异常体系下分为两大类:
- Error:程序员无法处理的异常。
- Exception:程序员可以处理的异常。
- Exception下分为两大类:
- 检查时异常(编译时异常):编译时发现的异常,必须经过处理,否则程序编译不能通过。
- 非检查时异常(运行时异常):运行时才发生的异常,可以不处理。
cho3.
常见的异常
(1)IllegalArgumentException 非法参数异常
Caused by java.lang.IllegalArgumentException No enum constant org.apache.ibatis.type.JdbcType.INT
描述:这是在MyBatis的mapper.xml中,由于编写的参数类型与定义好的枚举不匹配,出现异常。
分析思路:
- 查看日志信息(一般看框架的日志应该从最后一个报错的地方开始)。
- 翻译下报错信息。由于枚举常量中不存在org.apache.ibatis.type.JdbcType.INT,而造成IllegalArgumentException异常的出现。
- 查看org.apache.ibatis.type.JdbcType中存在哪些常量。
源码:
import java.util.HashMap;
import java.util.Map;
public enum JdbcType {
ARRAY(2003),
BIT(-7),
TINYINT(-6),
SMALLINT(5),
INTEGER(4),
BIGINT(-5),
FLOAT(6),
REAL(7),
DOUBLE(8),
NUMERIC(2),
DECIMAL(3),
CHAR(1),
VARCHAR(12),
LONGVARCHAR(-1),
DATE(91),
TIME(92),
TIMESTAMP(93),
BINARY(-2),
VARBINARY(-3),
LONGVARBINARY(-4),
NULL(0),
OTHER(1111),
BLOB(2004),
CLOB(2005),
BOOLEAN(16),
CURSOR(-10),
UNDEFINED(-2147482648),
NVARCHAR(-9),
NCHAR(-15),
NCLOB(2011),
STRUCT(2002),
JAVA_OBJECT(2000),
DISTINCT(2001),
REF(2006),
DATALINK(70),
ROWID(-8),
LONGNVARCHAR(-16),
SQLXML(2009),
DATETIMEOFFSET(-155);
public final int TYPE_CODE;
private static Map<Integer, JdbcType> codeLookup = new HashMap();
private JdbcType(int code) {
this.TYPE_CODE = code;
}
public static JdbcType forCode(int code) {
return (JdbcType)codeLookup.get(code);
}
static {
JdbcType[] var0 = values();
int var1 = var0.length;
for(int var2 = 0; var2 < var1; ++var2) {
JdbcType type = var0[var2];
codeLookup.put(type.TYPE_CODE, type);
}
}
}
得出结论:
根据源码可以看出,与INT类型相关的常量只有TINYINT(-6),SMALLINT(5),INTEGER(4),BIGINT(-5)四种,没有INT类型。需要根据情况选择正确的参数类型,否则就会出现该IllegalArgumentException。
(2)ClassNotFoundException 类未找到异常
java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
分析思路:
- 翻译报错信息:类未找到异常:(未找到)com.microsoft.sqlserver.jdbc.SQLServerDriver这个类。
- 这个问题是从JDBC到使用框架都常出现的,即项目中没有导入该数据库驱动包。
得出结论:
需要导入对应的驱动。
(3)SQLException SQL异常
java.sql.SQLException: Field 'id' doesn't have a default value
分析思路:
- 翻译报错信息:SQL异常:“id”域没有默认值。
- 在进行插入操作时,对应域的值没有传过去(或者为null),同时id这个字段本身也没有设置默认的值。
得出结论:
对于Id这个字段,一是可以为id设置一个初值,同时使该字段自动递增(id类型为int);二是在代码中添加生成id的逻辑部分。
(4)IllegalStateException 非法状态异常
java.lang.IllegalStateException:No typehandler found for property
分析思路:
- 翻译报错信息:非法状态异常:未找到该属性的类型处理器。
- 这个问题出现在Mybatis的使用过程,由于在xml中字段名称不小心写错导致的。
得出结论:
关于Mybatis框架这块,比较容易出问题(对于ssm项目)。因此要比较细心,出了与属性、字段等有关的错误,而其他地方一时找不到问题时,可以仔细检查xml文件中字段/属性的名称、类型。
(5)NumberFormatException 数字格式异常
java.lang.NumberFormatException: null
分析思路:
- 翻译报错信息:数字格式为null。
- 找到报错的位置,是controller层的参数报错。使用debug调试一下(也可以直接System.out,debug时间太长了),发现该参数是null。
得出结论:
参数没有传过来:一是前端没有发送该参数过来;二是设置的参数名称(或者类型)和前端不一致,导致传过来但映射不上。
(6)EOFException 文件结束异常
java.io.EOFException: Unexpected EOF read on the socket
分析思路:
- 翻译报错信息:文件结束异常:在socket上未读取到文件的EOF。
- 这个问题出现在完成一个文件上传功能时。由于文件没有到EOF就被中断传输了,这主要是因为文件上传超时了。
得出结论:
设置tomcat连接时长,在application.yml中添加配置:
server:
connection-timeout: 18000000
同时添加配置类:
@Configuration
public class ChoConfig {
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize(8 * 1024); //设置上传文件最大值
return factory.createMultipartConfig();
}
}
这里是springboot的解决方案,其他框架可以使用对应的解决方案
(7)NullPointerException 空指针异常
得出结论:
这个异常比较常见,尤其是初学时候或者项目比较庞大时,需要检查报错的对象是不是null就可以了。不过对象值为null的原因多种多样,要稍加思考。
cho4.
异常的创建、抛出、捕获、处理
异常的创建(自定义异常)
- 继承Exception
- 添加serialVersionUID
- 根据需要添加方法(如构造方法)
异常的抛出
- 异常抛出的两种方式
- 方式一:由JVM抛出。当系统出现异常时,JVM会讲异常封装为对象,并抛出给系统,由系统进行处理。
- 方式二:由代码手动抛出。当系统出现异常(或者满足自定义异常条件)时,创建一个异常对象,并抛出。
- 语法
//方法可能抛出的异常。
throws 异常1, 异常2……
//抛出自定义异常。
throw new 自定义异常;
注意:
- 异常的抛出是由产生异常的方法,层层抛出给调用方法,直到异常被处理或者抛给OS(程序终止)。
- 重写方法不能抛出比被重写方法范围更大的异常类型。
异常的捕获
语法:
//try要和catch[finally]搭配使用
try{
异常捕捉的区域。
}
异常的处理
语法
try{
异常捕捉的区域。
}
catch( 异常名称1 e ){
处理捕捉到的异常
}
catch( 异常名称2 e ){
处理捕捉到的异常
}
[ finally{
最终都会执行的语句:关闭io等
} ]
关于异常捕获与处理的例子,可以查看Javase复习系列——IO流中的demo。