前言:想要学好异常,需要了解JVM虚拟机知识,这里涉及面试常问的内存溢出错误解决办法
程序 编译时/运行过程中,由于某些原因导致程序出错,从而结束程序运行,这就称为异常
java异常的结构图(超类、子类关系等结构,此结构不是太全,可看下面“七、常见错误异常附录”)
Java 中所有的错误和异常最终都继承自 java.lang.Throwable 这个类。
(当然,Object类是Java中所有类的父类,也是Throwable的父类。不过这儿讨论的是异常,所以我们常说,异常的超类是Throwable 类。)
Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类。
Throwable下面一层只派生出2个子类:Error类 和 Exception类。
2.1 错误:Error类以及它的子类的实例,代表了JVM本身的错误。
错误不能被程序员通过代码处理,Error很少出现。
因此,程序员应该关注Exception为父类的分支下的各种子异常类。
2.2 异常: Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。
可以被Java异常处理机制使用,是异常处理的核心。(Exception分为:RuntimeException和非RuntimeException )
相同点:
一、都继承自Throwable类
二、都没有自己实现的方法,都是继承Throwable和Object的
三、都有四个构造方法,参数及实现的功能一样
不同点:
一、Error属于系统级错误称之为“错误”,不可被捕获,也就是无法用try catch/throw机制;
Exception属于应用程序级错误称之为“异常”,可以通过捕获避免,也就是可以用try catch/throw机制;
二、Error无需在程序中以throw子句中抛出; 而Exception需要抛出
三、存在Error错误程序不能运行或是运行中断; 存在Exception错误程序可运行并抛出
Java 定义了两种异常( C# 只有unchecked异常 ):
非受查异常 (Unchecked exception) / 运行时异常:
Error和子类、 继承自 Exception 的 RuntimeException和子类都称为非受查异常/运行时异常,
就是代码不需要强制处理它们的异常也能通过编译,所以它们称作 unchecked exception。RuntimeException(运行时异常)不需要try…catch…捕获机制或throw抛出机制去强制处理。
编译器不强制记录异常,但是!我们一般都建议手动捕获异常,做自己的逻辑处理。
生产中,非受查异常中的RuntimeException异常最常见~
受查异常 (checked exception) / 编译时异常:
继承自 Exception 的 非RuntimeException:IOException及子类、ReflectiveOperationException及子类、SQLException、InterruptedException等等,都是受查异常/编译时异常。代码需要强制处理抛出的异常,要么用 try catch 语句,要么直接用 throws 语句声明,否则编译不通过!!!
比如:FileNotFoundException, 不处理则会爆红,不能编译!编译器强制我们处理
生产中,这种异常不常见~
try :定义可能发生异常的代码 (监控区域)
catch:用来捕捉try中发生的异常(捕获异常区域)
finally:无论是否有异常都会执行的代码(处理善后工作)【除了在一种情况下不能被执行:当执行到System.exit(1)用来强制关闭虚拟机时】
throw :抛出异常
throws :声明异常
【注意事项】
即使try和catch块中存在return语句,finally语句也会执行。是在执行完finally语句后再通过return退出。
finally语句块只有一种情况是不会执行的,那就是在执行finally之前遇到了System.exit(0)结束程序运行。
public static void main(String[] args) {
FileReader reader = null;
try{
System.out.println("第0次打印...");
reader = new FileReader("D:/a.txt");
System.out.println("第1次打印...");
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
FileReader reader = null;
try{
System.out.println("第0次打印...");
reader = new FileReader("D:/a.txt");
System.out.println("第1次打印...");
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if (reader != null){
reader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
//假设下面的D:/a.txt不存在!!!!
public static void main(String[] args) {
FileReader reader = null;
try{
System.out.println("第0次打印...");
reader = new FileReader("D:/a.txt");
System.out.println("第1次打印...");
char c = (char)reader.read();
System.out.println("2"+c);
}catch(FileNotFoundException e){//子类异常放在父类异常前面
System.out.println("第3次打印...");
e.printStackTrace();
}catch(IOException e){ //父类异常放在异常后面
System.out.println("第4次打印...");
e.printStackTrace();
}finally{
System.out.println("第5次打印...");
try{
if (reader != null){
reader.close();
}
}catch (Exception e){
System.out.println("第6次打印...");
e.printStackTrace();
}
}
}
public static void main(String[] args) throws NullPointerException{
String a = null;
if (a.equals("张三")) {
System.out.println("我是张三");
}
}
public static void main( String[] args ) {
public String str =null;
try{
if(str.equals("张三")){
str = "李四";
}
}catch (Exception e){
//第1种
System.out.println("e.getMessage()打印结果: "+ e.getMessage());
//第2种
System.out.println("e.getLocalizedMessage()打印结果: "+ e.getLocalizedMessage());
//第3种
System.out.println("ExceptionUtils.getStackTrace()打印结果: "+ ExceptionUtils.getStackTrace(e));
//第4种
System.out.println("e.toString()打印结果: "+ e.toString());
System.out.println("============分割线=============");
//第5种
e.printStackTrace();
}
}
常见error:(未受查异常/运行时异常)
VirtualMachineError
OutOfMemoryException - 内存溢出异常(面试官问你:遇到这个,你怎么解决) (VirtualMachineError 的子类)
StackOverflowError - 深递归导致堆栈被耗尽而抛出的异常 (VirtualMachineError 的子类)
UnknownError - 未知错误 (VirtualMachineError 的子类)
ThreadDeath - 内存溢出异常(面试官可能问你:遇到这个,你怎么解决)
NoClassDefFoundError - 类定义错误异常
IOError
LinkageError
ClassFormatError - (LinkageError子类)
UnsatisfiedLinkError - (LinkageError子类)
…
常见RuntimeException:(未受查异常/运行时异常)
NullPointerException - 空指针引用异常
ClassCastException - 类型强制转换异常
IndexOutOfBoundsException - 下标越界异常
ArrayIndexOutOfBoundsException - 数组下标越界异常 (IndexOutOfBoundsException 的子类)
StringIndexOutOfBoundsException - (IndexOutOfBoundsException 的子类)
NegativeArraySizeException - 负数组长度异常
IllegalArgumentException - 传递非法参数异常
NumberFormatException - 字符串转数字类型异常 (IllegalArgumentException 的子类)
IllegalThreadStateException - 非法线程状态异常(IllegalArgumentException 的子类)
SecurityException - 违背安全原值异常
ArithmeticException - 算术运算异常
UncheckedIOException
ArrayStoreException
WrongMethodTypeException
UndeclaredThrowableException - 未声明的异常
TypeNotPresentException
IllegalStateException
IncompleteAnnotationException
AnnotationTypeMismatchException
IllegalMonitorStateException
MalformedParameterizedTypeException
MalformedParametersException
…
非RuntimeException 之 IOException相关:(受查异常/编译时异常)
FileNotFoundException - 文件找不到异常
FileSystemException
FilerException
InterruptedIOException
EOFException
SocketException
SyncFailedException
ZipException
UTFDataFormatException
UnsupportedEncodingException
ObjectStreamException
InvalidClassException (ObjectStreamException 的子类)
InvalidObjectException (ObjectStreamException 的子类)
NotSerializableException (ObjectStreamException 的子类)
OptionalDataException (ObjectStreamException 的子类)
WriteAbortedException (ObjectStreamException 的子类)
NotActiveException (ObjectStreamException 的子类)
…
非RuntimeException 之 ReflectiveOperationException相关 (受查异常/编译时异常)
ClassNotFoundException - 类文件找不到异常
NoSuchFieldException - 没有此属性异常
NoSuchMethodException - 没有此方法异常
IllegalAccessException -
InstantiationException -
InvocationTargetException -
…
非RuntimeException 之 SQLException:(受查异常/编译时异常)
非RuntimeException 之 InterruptedException:(受查异常/编译时异常)
非RuntimeException 之 IllegalClassFormatException:(受查异常/编译时异常)
非RuntimeException 之 LambdaConversionException:(受查异常/编译时异常)
非RuntimeException 之 CloneNotSupportedException:(受查异常/编译时异常)
非RuntimeException 之 UnmodifiableClassException:(受查异常/编译时异常)
常见error解决方案:
那么如何定义自定义异常呢?
1.定义自定义异常类时可以继承Throwable类或者Exception类,但通常都是继承Exception类来实现。也可以通过继承RuntimeException类来定义运行时异常,但不要继承Error类。(我们单位自定义的异常是继承于RuntimeException)
在自定义异常类中一般会定义两个构造方法,分别是无参构造方法;还有一个是带一个字符串参数的构造方法,这个字符串将作为描述该异常对象的异常信息。
2.一般在定义自定义异常类时类名都是以Exception结尾。
3.如果继承Exception类产生的编译时异常,在代码中必须使用 throw或者try-catch关键字来处理这个异常,而继承RuntimeException类产生的运行期异常可以不用处理。
https://blog.csdn.net/qq_45055856/article/details/97817768
https://blog.csdn.net/m0_67929156/article/details/124112811
https://blog.csdn.net/m0_54189068/article/details/127106337
https://blog.csdn.net/song12345xiao/article/details/126489652
https://blog.csdn.net/qq_40041868/article/details/123471481
https://blog.51cto.com/u_15271242/2909987
http://events.jianshu.io/p/3714a154adf8
https://www.ngui.cc/el/423994.html?action=onClick
https://blog.csdn.net/Jin_Kwok/article/details/79866465
https://www.bbsmax.com/A/D85432YVJE/