1 异常概述
异常:程序执行过程中,产出的问题,因为异常的问题程序的正常的逻辑中断。
Java程序在执行过程中所发生的异常事件可分为两类:
- Error: Java虚拟机无法解决的严重问题。 如: JVM系统内部错误、 资源耗尽等严重情况。
StackOverflowError:栈深度溢出异常,比如递归方法,没有退出条件
java.lang.OutOfMemoryError:OOM内存溢出异常,栈,堆,方法区,程序计数器不会发生 - Exception: 其它因编程错误或偶然的外在因素导致的一般性问题, 可以使用针对性的代码进行处理。
RuntimeException:运行期异常,编译是不需要处理
ClassCastException
ArrayIndexOutOfBoundsException
ArithmeticException
NullPointerException
非RuntimeException:编译期需要处理(try catch 或者throws)
FileNotFoundException
IOException
SQLException
异常层次结构图:
2 堆内存OOM
1.测试代码
public class Test1 {
static class OOM{
// int i = 0;
}
/**
* xms:初始化堆内存
* xmx:最大堆内存
* 360146 10m
* 810326 20m
* 1215488 40m
* @param args
*/
public static void main(String[] args) {
System.out.println("前面代码");
List<OOM> list = new ArrayList<>();
int i=0;
try {
while (true) {
i++;
list.add(new OOM());
}
} catch (Throwable e) {
System.out.println("=================多少次后发生异常:"+i);
e.printStackTrace();
}
}
}
2.设置jvm参数
- xmx20m:最大堆内存大小20m
- xms10m:初始堆内存大小10m
3.运行结果
3 方法区(元空间)OOM
1.测试代码:
public class MetaspaceDemo {
static class OOM{}
public static void main(String[] args) {
int i = 0;//模拟计数多少次以后发生异常
try {
while (true){
i++;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOM.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o,args);
}
});
enhancer.create();
}
} catch (Throwable e) {
System.out.println("=================多少次后发生异常:"+i);
e.printStackTrace();
}
}
}
2.设置jvm参数
-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
3.运行结果
4 StackOverflowError栈深度溢出异常
1.测试代码
static void f1(){
int i=1;
f1();
}
/**
* StackOverflowError:栈寻址深度溢出异常,递归没有退出条件
*/
@Test
public void f2() {
System.out.println("前面代码");
f1();
System.out.println("后续代码");
}
2.运行结果
5 其他异常
1.测试代码
public class Test1 {
/**
* 空指针异常
*/
@Test
public void f3() {
System.out.println("前面代码");
String s = null;
s.trim();
System.out.println("后续代码");
}
/**
* java.lang.ArithmeticException: / by zero:0作为除数异常
*/
@Test
public void f4() {
System.out.println("前面代码");
int i = 1/0;
System.out.println("后续代码");
}
}
2.运行结果
- f3( )测试结果:
- f4( )测试结果:
6 异常处理
在Java中,异常是指在程序执行过程中可能发生的错误或异常情况,这些情况可能导致程序中断或出现未预期的行为。常见的异常包括空指针异常、数组越界异常、算术异常等。
Java提供了异常处理机制来处理这些异常情况,异常处理主要包括以下几个关键字和语句:
try:用于包裹可能抛出异常的代码块,表示尝试执行其中的代码。
catch:用于捕获并处理异常,在try块中发生异常时,程序会跳转到对应的catch块进行处理。
finally:可选的代码块,在try块中的代码执行完毕后,无论是否发生异常,都会执行finally块中的代码。
throw:用于抛出异常,可以在程序中手动抛出异常。
throws:用于声明方法可能抛出的异常,在方法签名中声明。
1.try、catch、finally
异常处理的基本流程是:程序首先尝试执行try块中的代码,如果出现异常,则根据异常类型跳转到对应的catch块进行处理。如果try块中的代码没有发生异常,则跳过catch块,执行finally块中的代码(如果有的话)。无论是否发生异常,finally块中的代码都会被执行。
异常处理的基本语法结构如下:
try {
// 可能抛出异常的代码块
} catch (异常类型1 变量名1) {
// 处理异常1的代码
} catch (异常类型2 变量名2) {
// 处理异常2的代码
} finally {
// 可选的finally代码块
}
示例:
@Test
public void f5(){
//类型转换异常ClassCastException
Object o = "abc";
Integer i = (Integer) o;
//算术运算异常ArithmeticException
int a = 1/0;
//空指针异常NullPointerException
String s = null;
s.trim();
}
@Test
public void f6() {
System.out.println("步骤1");
try {
f5(); //共享单车车胎坏了
} catch (ClassCastException e) {
System.out.println("ClassCastException");
//换了一个车
e.printStackTrace(); //f6在调用f5的时候123行异常
} catch (NullPointerException e) {
//轱辘没了...
System.out.println("NullPointerException");
e.printStackTrace();
} catch (Exception e) { //兜底,捕获除了上面2个异常的所有异常
System.out.println("OthersException");
e.printStackTrace();
} finally {
System.out.println("还共享单车"); //释放资源,必须执行的代码
}
System.out.println("步骤3");
//运行期异常RuntimeException的子类,不需要处理,编译也不报错
}
在f6()
方法中调用f5()
方法时发生了ClassCastException
异常,然后在f6()
方法中捕获并处理了该异常。接着程序继续执行,输出 “还共享单车” 和 “步骤3”。其中,ClassCastException
异常被catch
块捕获,而后面的ArithmeticException
异常和NullPointerException
异常并没有被catch
块捕获,所以它们没有被处理,直接抛出到上层调用栈,最后在控制台输出异常堆栈跟踪信息。
2.throws
throws:声明异常,当前方法不捕获(catch)异常,而是由调用这个方法的方法catch异常。
示例:
public static void fn1() throws IOException {
DataOutputStream out = new DataOutputStream(new FileOutputStream("d:\\c.txt"));
out.writeChar(97); //若发生异常
out.writeInt(1);
out.writeChar(98);
out.close(); //有可能执行不到
}
public static void main(String[] args) {
try {
fn1();
} catch (IOException e) {
e.printStackTrace();
}
}
3.throw与自定义异常
示例:
(1)自定义异常MyException
public class MyException extends Exception{
public MyException() {
}
public MyException(String message) {
super(message);
}
}
(2)创建Student实体类
public class Student {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
if(id > 0){
this.id = id;
}else {
throw new RuntimeException(new MyException("id不能为负"));
}
}
}
(3)测试
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.setId(-1);
}
}
结果: