异常、日志、断言和调试
异常
处理异常
程序运行出现错误:程序应该返回到一种安全状态,能够让用户执行一些其它的命令;允许用户保存所有操作的结果,以适当方式终止程序
程序可能出现的错误:用户输入错误,设备错误,物理限制,代码错误
方法并不返回任何值,而是抛出一个封装了错误信息的对象
异常对象都是派生于throwable类的一个实例,有两个分支
Error类:描述了java运行时系统的内部错误和资源耗尽错误,JVM错误,程序无法处理
Exception和RunntimeException的区别:
①,Exception在程序中必须进行try-catch处理。
②,RunntimeException可以不使用try-catch处理,但是如果有异常产生,则异常将由jvm进行处理。
Exception:两个分支,RuntimeException:由程序导致的错误。其它异常:像I/O错误;RuntimeException异常:错误的类型转换,数组访问越界(ArrayIndexOutOfBoundsException),访问空指针(NullPointerException)
声明已检查的异常
已检查的异常就是指自己知道会放发生的异常
如果遇到无法处理的情况,java的方法可以抛出一个异常
一个方法必须声明所有可能抛出的已检查异常,未检查异常要么不可控制,要么避免发生
抛出异常时机:调用一个抛出已检查异常的方法;程序运行过程中发现错误;程序出现错误;Java虚拟机和运行时库出现的内部异常
如何抛出异常
确认异常的类型,找到一个合适的异常类,创建这个类的一个对象,将对象抛出
throw抛出的是一个异常类的实例化对象,必须要进行try-catch处理,可以自己抛出异常对象
创建异常类
包含两个构造器:默认的构造器,带有详细描述信息的构造器
捕获异常
try catch语句
如果编写一个覆盖超类的方法,而这个方法没有抛出异常,这个方法就必须捕获方法代码中出现的每一个已检查异常
捕获多个异常
在catch子句中可以抛出一个异常,改变异常的类型
对于异常,可以使用finally设置统一的出口,不管是否有异常都会执行该语句
如果主方法中只抛出异常,不处理,异常会被交给jvm处理
Java默认的异常处理是使用jvm完成的
public class Throw{
public static void main(String[] args){
try{
throw new Exception("我自己抛出自己,好吧");
}catch(Exception e){
System.out.println(e);
}
}
} ;
try-catch-finally,throws
package java核心技术1;
class Math{
public int div(int i,int j) throws Exception{
System.out.println("除法:");
int temp = 0;
try {
temp = i/j;
}catch(Exception e) {
throw e;
}finally {
System.out.println("计算结束");
}
return temp;
}
};
public class ThrowsDemo {
public static void main(String[] args) {
Math m = new Math();
try {
System.out.println(m.div(10, 0));
}catch(Exception e) {
System.out.println("异常产生:"+e);
}
}
}
分析堆栈跟踪元素
堆栈跟踪时一个方法调用过程的列表。当java程序正常终止,没有捕获异常时,会显示该列表
getStackTrace方法获得一个StackTraceElement对象的数组
StackTraceElement类可以获得文件名和当前执行的代码行号
递归阶乘的堆栈情况
public int maxDepth (TreeNode root){
if(root == null){
return 0;
}
int res=0;
List<TreeNode> queue = new LinkedList<>();
List<TreeNode> tmp;
queue.add(root);
while(!queue.isEmpty()){
tmp = new LinkedList<>();
for(TreeNode e:queue){
if(e.left != null){
tmp.add(e.left);
}
if(e.right != null){
tmp.add(e.right);
}
}
queue = tmp;
res++;
}
return res;
}
public static int factorial(int n){
System.out.println("factorial(" + n + "):");
Throwable t = new Throwable();
StackTraceElement[] frames = t.getStackTrace();
for(StackTraceElement f:frames){
System.out.println(f);
}
int r;
if(n <= 1){
r = 1;
}
else{
r = n * factorial(n-1);
}
System.out.println("return " + r );
return r;
}
public static void main(String[] args) {
// write your code here
Scanner in = new Scanner(System.in);
System.out.println("enter n:");
int n = in.nextInt();
factorial(n);
}
自定义异常类
继承Exception就可以自定义一个自己需要的异常类了,当然继承RunntimeException也是可以的。
package java核心技术1;
class MyException extends Exception{
public MyException(String msg) {
super(msg);
}
};
public class Default {
public static void main(String[] args) {
try {
throw new MyException("自定义异常");//抛出异常
}catch(Exception e) {
System.out.println(e);
}
}
}
异常处理不能代替简单的测试
不要过分的细化异常
利用异常层次结构
不要压制异常
细心检查错误
不要羞于传递异常
断言
在测试期间向代码中插入一些检查语句
默认情况下,断言被禁用
启用或禁用断言是类加载器的功能
断言失败是不可恢复的错误,只用于开发和测试阶段
不应该使用断言向程序的其它部分通告发生了可恢复性的错误
调试
1.java类库中的绝大多数类都覆盖了toString方法,能够提供有用的类信息
2.在每一个类中放置一个main方法,对每一个类进行单元测试
3.JUnit是一个单元测试框架
4.日志代理是一个子类的对象,窃取方法调用,进行日志记录
5.利用throwable类提供的printStackTrace方法,从任何一个异常对象中获得堆栈情况
StringWriter out = new StringWriter();
new Throwable().printStackTrace(new PrintWriter(out))//将堆栈跟踪记录发送到文件中
String trace = out.toString;
7.捕获错误流
8…
参考:Java核心技术1,https://blog.csdn.net/jakezhang1990/article/details/72880700?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight