注解: 注释 给编译器看
@Override: 判断方法是否重写(用于校验是否重写 如果不符合重写规范就会报错)
@Deprecated:标记过时
@SuppressWarnings("all"): 抑制警告 (可以有参数)
异常的体系:
Throwable
-- Error 错误 不能处理的
-- Exception 异常
-- 运行时异常 代码真正跑起来
-- 编译时异常 写完代码就报错
import org.junit.Test;
public class TestError {
@Test
public void test01(){
a();
}
private void a() {
a();
}
}
@Test
public void test2(){
int arr [] = new int[21_0000_0000];
System.out.println(Arrays.toString(arr));
}
Error:
StackOverflowError
OutOfMemoryError
ArithmeticException:算数异常
除数为0
NullPointerException
ClassCastException
ArrayIndexOutofBoundsException
InputMismatchException: 输入不匹配异常
FileNotFoundException
InterruptedException
向下执行 向上抛出
public class TestException {
public static void main(String[] args) {
method01();
}
private static void method01() {
method02();
}
private static void method02() {
method03();
}
private static void method03() {
method04();
}
private static void method04() {
int[] arr = {10,20};
System.out.println(arr[23]);
System.out.println("Game Over");
}
}
有图可知,jvm由main方法进入程序开始i执行method01(),进行连续调用method02(),method03(),method04(),此时出现异常,jvm会看一下当前又没有对异常的处理,如果没有则向上抛到method03(),继而抛到method02(),method01(),最后到达main()方法,如果此时还没有处理,那么就会抛给JVM虚拟机
因此再查看异常信息的时候,要从上往下看,最上边的是异常的发源地。
public class ThrowTest {
public static void main(String[] args) {
int [] arr = {10,20,40,20};
// method(null);
method(arr);
}
private static void method(int[] arr) {
if (arr == null){
throw new NullPointerException("空指针异常");
}
if (arr.length > 3){
throw new ArrayIndexOutOfBoundsException("数组下标越界");
}
}
}
try{
可能发生异常的代码
}catch(异常类型 变量名){
发生异常后的代码
}
注意:
1.发生异常后 try中异常下面的代码不执行 会看一下 catch能否捕获发生的异常2.当发生了不能捕获的异常 结束程序
3.捕获多个异常
3.1 使用 | 连接 异常类型1 | 异常类型2|... 变量名
3.2 多重catch 将大的范围的异常写到后面(否则小范围的异常将不会被触发)
4.try中声明的变量 只能在try中使用 其他位置想要使用 要进行作用域提升Throwable
a.printStackTrace();答疑异常的堆栈信息
a.getMessage();获取异常的原因
public static void main(String[] args) {
try {
int[] arr = {10, 20};
System.out.println("11111");
int i = 10/0;
// System.out.println(arr[12]);
System.out.println("33333");
} catch (ArrayIndexOutOfBoundsException a) {
a.printStackTrace();
String message = a.getMessage();
System.out.println("message = " + message);
}catch (ArithmeticException a){
a.printStackTrace();
String message = a.getMessage();
System.out.println("message = " + message);
}catch (Exception e){
}
System.out.println("Game Over");
}
try{}catch(){}finally:
finally: 无论是否发生异常都有执行的代码如果不想要执行finall里面的内容:
System.exit(0); 退出jvm
public static void main(String[] args) {
try {
int[] arr = {10, 20};
System.out.println("11111");
int i = 10/2;
// System.out.println(arr[12]);
System.out.println("33333");
// return;
System.exit(0);
} catch (ArithmeticException e){
e.printStackTrace();
}finally {
System.out.println("Game Over");
}
}
throws vs throw
1.位置不同
throws:方法的声明处
throw:方法内
2.数量不同
throws 后面可以有多个异常【类型】
throw 后只能有一个异常对象3.作用不同
throw 手动抛出异常对象
throws 通知方法调用者 调用本方法可能出现的问题注意:
1.如果抛出的是运行时异常 方法声明处可以不用声明
2.如果抛出的是编译时异常 且没有进行处理 那么方法声明处 必须 throws 声明
3.只要是声明了编译时异常 一旦调用 必须处理
public class Test {
public static void main(String[] args) {
try {
method1();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private static void method1() throws ArrayIndexOutOfBoundsException, ArithmeticException, FileNotFoundException {
if(3>2){
throw new ArrayIndexOutOfBoundsException();
}
if(3<4){
throw new ArithmeticException("算数异常");
}
if(4>5){
throw new NullPointerException();
}
if(6>8){
throw new FileNotFoundException();
}
}
}
public class FinallyReturn {
public static void main(String[] args) {
int num = method();
System.out.println("num = " + num);
}
private static int method() {
int num = 90;
try {
int[] arr = {10, 20};
System.out.println(arr[20]);
return 30;
} catch (Exception e) {
e.printStackTrace();
return 40;
} finally {
return 50;
}
}
}
public class FinallyReturn1 {
public static void main(String[] args) {
int num = method();
System.out.println("num = " + num);
}
private static int method() {
int num = 90;
try {
int[] arr = {10, 20};
System.out.println(arr[20]);
return num;
} catch (Exception e) {
e.printStackTrace();
num = 70;
return num;//临时变量 记录好 即将返回的值
} finally {
num = 60;
// return num;
}
}
}
子类不能抛出比父类更大的异常,这句话有bug
应该是 编译时异常 子类不能抛出比父类更大的异常
运行时异常无所谓
RuntimeException和IOException都继承于Exception,Exception属于编译时异常,因为编译时一场更加严格。范围更大。
子类重写父类方法时
1.权限修饰符 子类不能比父类更加严格 >=父类的访问权限2.返回值类型
父类方法的返回值类型是 基本数据类型 子类重写时 要与父类一致
父类方法的返回值类型是 引用数据类型 子类重写时 可以与父类一致 也可以是 父类返回值类型的子类3.方法名 形参列表 必须与父类方法一致
4.异常
如果父类抛出的是运行时异常 那么此类无所谓
如果父类抛出的是编译时异常 那么子类不能抛出比父类更大的异常注意:
Exception 是编译时异常
public class Person {
public void show() throws NullPointerException {
}
public void method() throws FileNotFoundException {
}
}
class Son extends Person {
@Override
public void method() throws FileNotFoundException {
}
@Override
public void show() {
}
}
如何实现自定义异常?
1.新建一个类 AgeException2.此类继承一个系统异常类型
2.1 如果希望是运行时异常 就继承运行时异常类
2.2 如果希望是编译时异常 就继承编译时异常类3.写俩构造器
无参
有参
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
setAge(age);
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 150){
this.age = age;
}else {
throw new AgeException("您输入的年龄不合法");
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class AgeException extends RuntimeException {
public AgeException() {
}
public AgeException(String message) {
super(message);
}
}