异常笔记
异常举例
数组下标越界
package exception;
/**
* Created by zengjx on 2019/4/25.
*/
public class ExceptionDemo1 {
public static void main(String[] args){
int[] arr =new int[3];
System.out.println(arr[3]);//数组越界
}
}
/***
* 输出结果:ArrayIndexOutOfBoundsException
* Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at exception.ExceptionDemo1.main(ExceptionDemo1.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
*/
异常是什么?
异常是在程序运行过程中发生了不正常情况,是对问题的描述。将问题进行对象的封装。成异常类
异常体系是什么?
异常体系:
Throwable
|–Error 直接已知子类,只有构造方法。其他方法继承父类。
|–Exception直接已知子类,只有构造方法。其他方法继承父类。
|–RuntimeException
改体系的特点;
子类的后缀都是其父类名。
Error类:
异常的分类
1,编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。
这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。
这样的问题都可以针对性的处理。
2,编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类。
这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的而或者引发了内部状态的改变导致的。
那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。
所以自定义异常时,要么继承Exception。要么继承RuntimeException。
RuntimeException 在正常运行抛出。无需声明
异常体系的特点有哪些?
异常体系中的所有类以及建立的对象都具备可抛性。
也就是说可以被throw和throws关键字所操作。
只有异常体系具备这个特点。
异常分为两大类:
Thrawable:
1. 一般不可处理的 Error;
特点:jvm 抛出的严重错误,一般不针对性处理,直接修改代码。
开辟空间太大,内存溢出:
public class ExceptionDemo1 {
public static void main(String[] args){
int[] arr =new int[3];
// System.out.println(arr[3]);//数组越界
int[] arr2 =new int[1024*1024*8000];// 8000M
}
}
Exception in thread “main” java.lang.NegativeArraySizeException
at exception.ExceptionDemo1.main(ExceptionDemo1.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
**2. 可以处理的 Exception**
抛出异常
对象需要需要可抛性—Throwable 子类
if(time<0){
new FuTime(); //这个对象包含问题的名称信息,位置。
}
无论是Error 还是异常,问题发生就应该抛出,让调用者知道并处理。
可抛性到底是什么? 怎么体现可抛性?
凡是被throw 和throws 操作的都具有可抛性。
异常原理
package exception;
/**
* Created by zengjx on 2019/4/25.
*/
class ArrayDdemo{
public void method(int[] arr,int index){
System.out.println(arr[index]);
}
}
public class ExceptionDemo1 {
public static void main(String[] args){
int[] arr =new int[3];
// System.out.println(arr[3]);//数组越界
/// int[] arr2 =new int[1024*1024*8000];// 8000MArr
ArrayDdemo d= new ArrayDdemo();
d.method(arr,3);
}
}
/*** 控制台显示 异常位置信息
com.intellij.rt.execution.application.AppMain exception.ExceptionDemo1
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 3
at exception.ArrayDdemo.method(ExceptionDemo1.java:10)
at exception.ExceptionDemo1.main(ExceptionDemo1.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
*/
异常发生 后后面的语句不会继续执行;
**
* Created by zengjx on 2019/4/25.
*/
class ArrayDdemo{
public void method(int[] arr,int index){
System.out.println(arr[index]);
System.out.println("haha");//不会执行 不会输出
}
}
public class ExceptionDemo1 {
public static void main(String[] args){
int[] arr =new int[3];
// System.out.println(arr[3]);//数组越界
/// int[] arr2 =new int[1024*1024*8000];// 8000MArr
ArrayDdemo d= new ArrayDdemo();
d.method(arr,3);
System.out.println("over");//不会输出
}
}
throw 和 thows 的区别?
throw定义在函数内,用于抛出异常对象。
(抛出多个异常)
1.throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。
2.当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,否则编译失败。
3.注意,RuntimeException除外。也就说,函数内如果抛出的RuntimeExcpetion异常,函数上可以不用声明。
如果函数声明了异常,调用者需要进行处理。处理方法可以throws可以try。
异常有哪几种?
1.编译被检测异常
该异常在编译时,如果没有处理(没有抛也没有try),编译失败。
该异常被标识,代表这可以被处理。
2.运行时被检测异常
在编译时,不需要处理,编译器不检查。
该异常的发生,建议不处理,让程序停止。需要对代码进行修正。
异常捕获 ,异常处理语句怎么写?
try
{
需要被检测的代码;
}
catch (异常类 变量 )// 用于接收异常对象
{
处理异常的代码;
}
finally
{
一定会执行的代码;
}
有三个结合格式:
-
try
{
}
catch ()
{
} -
try
{}
finally
{}
-
try
{}
catch ()
{
}
finally
{}
finally 的作用是什么?,什么时候不执行?
1,finally中定义的通常是 关闭资源代码。因为资源必须释放。
2,finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。
怎样 自定义异常?
定义类继承Exception或者RuntimeException 按照面向对象的思想,对异常进行封装。
1,为了让该自定义类具备可抛性。
2,让该类具备操作异常的共性方法。
当要定义自定义异常的信息时,可以使用父类已经定义好的功能。
异常异常信息传递给父类的构造函数。
class MyException extends Exception
{
MyException(String message)
{
super(message);
}
}
package exception;
class Demo{
public int method(int[] arr, int index ){
if(index>=arr.length){
throw new ArrayIndexOutOfBoundsException("数组下标越界");
}
return arr[index];
}
}
public class ExceptionDemo1 {
public static void main(String[] args){
int[] arr =new int[3];
Demo demo=new Demo();
demo.method(arr,3);
}
}
自定义空指针异常
package exception;
class Demo{
public int method(int[] arr, int index ){
if(arr==null){
**throw new NullPointerException("数组的引用不能为空");**
}
if(index>=arr.length){
throw new ArrayIndexOutOfBoundsException("数组下标越界");
}
return arr[index];
}
}
public class ExceptionDemo1 {
public static void main(String[] args){
int[] arr =new int[3];
Demo demo=new Demo();
// demo.method(arr,3);
demo.method(null,3);
}
}
自定义异常类
继承与Exception ,并且哪里有用到这个异常类就必须声明 ,否则会报错。只需实现构造方法。其他方法父类已经实现,例如要显示异常信息构造方法:只需要 调用 super(String s);
class FuShuIndexException extends Exception{
FuShuIndexException(){
}
FuShuIndexException(String msg){
**super(msg);//父类 thowable 已经包含这个方法**
}
}
package exception;
class FuShuIndexException extends Exception{
FuShuIndexException(){
}
FuShuIndexException(String msg){
super(msg);//父类 thowable 已经包含这个方法
}
}
class Demo{
public int method(int[] arr, int index )throws FuShuIndexException{//声明FuShuIndexException
if(arr==null){
throw new NullPointerException("数组的引用不能为空");
}
if(index>=arr.length){
throw new ArrayIndexOutOfBoundsException("数组下标越界");
}
if(index<0){
throw new ArrayIndexOutOfBoundsException("数组下标为负数");
}
return arr[index];
}
}
public class ExceptionDemo1 {
public static void main(String[] args) throws FuShuIndexException{//声明FuShuIndexException
int[] arr =new int[3];
Demo demo=new Demo();
// demo.method(arr,3);
demo.method(arr,-3);
}
}
如果没有声明自定义的异常类可能出现编译问题:
啥时候try 啥时候 thow抛 ?
这个时候不需要try 因为异常不是method 方法自身产生的。功能没毛病。是调用的问题,把问题暴露出来。
如果一个问题可以处理就用try ,否则就用throw抛。
一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理。
内部又几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
ExceptionDemo4 :
class FuShuIndexException extends Exception
{
FuShuIndexException()
{}
FuShuIndexException(String msg)
{
super(msg);
}
}
class Demo
{
public int method(int[] arr,int index)throws NullPointerException,FuShuIndexException
{
if(arr==null)
throw new NullPointerException("没有任何数组实体");
if(index<0)
throw new FuShuIndexException();
return arr[index];
}
}
class ExceptionDemo4
{
public static void main(String[] args)
{
int[] arr = new int[3];
Demo d = new Demo();
try
{
int num = d.method(arr,-1);
System.out.println("num="+num);
}
catch(NullPointerException e)
{
System.out.println(e.toString());
}
catch (FuShuIndexException e)
{
System.out.println("message:"+e.getMessage());
System.out.println("string:"+e.toString());
e.printStackTrace();//jvm默认的异常处理机制就是调用异常对象的这个方法。
System.out.println("负数角标异常!!!!");
}
/*
catch(Exception e)//多catch父类的catch放在最下面。
{
}
*/
System.out.println("over");
}
}
输出结果: 异常捕获后还会继续执行下面的代码。
执行流程;
异常处理 多个catch
多个catch 时候,一定要把父类Exception 放在其他子类的下面。否则编译失败。考点:多个catch 执行哪一个?
finally 什么时候执行,什么时候不执行?
情况1:
package exception;
class FuShuIndexException5 extends Exception
{
FuShuIndexException5()
{}
FuShuIndexException5(String msg)
{
super(msg);
}
}
class Demo5
{
public int method(int[] arr,int index)throws NullPointerException,FuShuIndexException5
{
if(arr==null)
throw new NullPointerException("没有任何数组实体");
if(index<0)
throw new FuShuIndexException5();
return arr[index];
}
}
public class ExceptionDemo5 {
public static void main(String[] args)
{
int[] arr = new int[3];
Demo5 d = new Demo5();
try
{
int num = d.method(arr,-1);
System.out.println("num="+num);
}
catch(NullPointerException e)
{
System.out.println(e.toString());
}
catch (FuShuIndexException5 e)
{
System.out.println("message:"+e.getMessage());
System.out.println("string:"+e.toString());
e.printStackTrace();//jvm默认的异常处理机制就是调用异常对象的这个方法。
System.out.println("负数角标异常!!!!");
}finally {
System.out.println("finally");
}
/*
catch(Exception e)//多catch父类的catch放在最下面。
{
}
*/
System.out.println("over");
}
}
输出结果:finaly
over
情况2: 异常处理catch 里面执行 return ; 此时over 不会执行,finally 会执行。
情况3:异常处理catch 里面有 System.exit(0).只有此时finally 不会执行 虚拟机结束了。
catch (FuShuIndexException5 e)
{
System.out.println("message:"+e.getMessage());
System.out.println("string:"+e.toString());
e.printStackTrace();//jvm默认的异常处理机制就是调用异常对象的这个方法。
System.out.println("负数角标异常!!!!");
System.exit(0);
}finally {
System.out.println("finally");
}
/*
catch(Exception e)//多catch父类的catch放在最下面。
{
}
*/
System.out.println("over");
异常处理的好处?
1,将问题进行封装。
2,将正常流程代码和问题处理代码相分离,方便于阅读。
异常处理的原则是什么?
1,函数内容如果抛出需要检测的异常,那么函数上必须要声明。
否则必须在函数内用trycatch捕捉,否则编译失败。
2,如果调用到了声明异常的函数,要么trycatch要么throws,否则编译失败。
3,什么时候catch,什么时候throws 呢?
功能内容可以解决,用catch。
解决不了,用throws告诉调用者,由调用者解决 。
4,一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理。
内部又几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
异常处理注意事项?
在子父类覆盖时:
1,子类抛出的异常必须是父类的异常的子类或者子集。
2,如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。{ 去掉 Fu 的 throw AException 保留 Zi 的throws 后 Error:(34, 21) java: exception.Zi中的method(int)无法覆盖 exception.FuDemo中的method(int)
被覆盖的方法未抛出exception.BException
}
// 不能catch
class ZiDemo extends FuDemo{
public void method(int num) {
if(num<0){
try{
}catch ( BException e){// Error:(39, 12) java: 在相应的 try 语句主体中不能抛出异常 错误exception.BException
e.printStackTrace();
}
}
}
//
class AException extends Exception{
}
class BException extends AException{
}
class CException extends Exception{
}
class Fu {
public void method(int num) throws AException{
if(num<0){
throw new AException(" FuDemo");
}
}
}
}
class Zi extends Fu{
public void method(int num) throws AException{// 可以
}
public void method2(int num ) throws BException{// 可以
}
public void method3() throws CException{ //不可以
编译报错 :Error:(37, 21) java: exception.ZiDemo中的method(int)无法覆盖 exception.FuDemo中的method(int)
被覆盖的方法未抛出exception.CException
}
}
父类没有抛 子类覆盖不能抛
interface A {
void function();
}
class D implements A{
@Override
public void function() throws Exception{//编译报错
}
}
只能 try
class E implements A{
@Override
public void function() {
try{
}catch ( Exception e){
e.printStackTrace();
}
}
}