Java基本语法
在之前学习Python的时候,就曾经接触过抛出异常 ,但当时对面向对象语言还不是很了解,草草看完就没了下文,实际上并没有搞懂,借着Java中相类似的内容,希望能够真正搞明白,并记录下来作为此次学习笔记。
在Java语言中, 将程序执行中发生的不正常情况称为“异常” 。“异常”是一种Exception类型的对象。
通常,我们可以将异常分为两类:
Java的异常处理机制是一个简捷、轻量化的执行期间例外状况处理方式,它让你能够将处理错误的程序代码摆在一个容易阅读的位置。
处理顺序通常为:
在定义方法时候通过 thows方法抛出Exception 在 try/catch块中接住抛出的异常
因为异常是一个类,所以可以被继承。异常可以被继承的好处在于,方法可以不必明确地声明每个可能抛出的异常,可以只声明父类。对于catch块来说,也可以不用对每个可能的异常作处理,只要有一个或少数几个catch可以处理所有的异常就够了。
如果我们想通过抛出异常的方式来测试代码有没有问题的时候,我们通常需要手写一个异常的类,来使用throw-try-catch这一套流程。前面我们说到,抛出的异常是一个类,所以我们自己定义的异常必须继承这个类。
代码示例:
class BadException extends Exception{
}
throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结 束当前方法的执行。
语法:
throw new 异常类名(参数);
示例代码:
public class DemoThrow {
public static void main(String[] args) {
int result = DemoThrow.div(4,0);
System.out.println(result);
}
public static int div(int a,int b)
{
if(b == 0)
throw new ArithmeticException("异常信息:除数不能为0"); //抛出具体问题,编译时不检测
return a/b;
}
}
输出结果: Exception in thread “main” java.lang.ArithmeticException: 异常信息:除数不能为0
运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常。通常用于一个方法(中的语句执行时)可能生成某种异常, 但是并不能确定如何处理这种异常的情况。
语法:
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2 ... { }
示例代码:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class DemoThrows {
public static void main(String[] args) throws FileNotFoundException{
readFile();
}
public static void readFile() throws FileNotFoundException {
InputStream is = new FileInputStream("test.txt");
}
}
输出结果: Exception in thread “main” java.io.FileNotFoundException: test.txt (No such file or directory)
像上述实例我们只使用了throws方法,并没有把调用放在try/catch块中,此时throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉,也就是我们所说的“Ducking”。
这只是一种“踢皮球”的行为,此时这些异常被Duck掉后,程序可以通过编译,但是如果希望程序完善的话,还是需要处理掉抛出的异常。
语法:
try {
//监视代码执行过程,一旦返现异常则直接跳转至catch,
// 如果没有异常则直接跳转至finally
} catch (SomeException e) {
//可选执行的代码块,如果没有任何异常发生则不会执行;
//如果发现异常则进行处理或向上抛出。
} finally {
//必选执行的代码块,不管是否有异常发生,
// 即使发生内存溢出异常也会执行,通常用于处理善后清理工作。
}
捕获异常的第一步是用try{}语句块选定捕获异常的范围, 将可能出现异常的方法放在try语句块中进行调用。如果try块失败了,即运行的代码出现异常,会生成一个异常并抛出,这里需要注意的是,一个try块可能会抛出多个异常,而每个异常都会对应一个catch块。出现异常后,流程会马上进入对应的catch块;如果整段try块没有抛出异常,运行结束后,会进入finally块或直接运行程序剩下的代码。
一个catch块接收try块抛出的一个异常。catch块的作用主要是尝试修复抛出的问题,如果无法在catch块中解决抛出的问题,也最好使用printStackTrace()方法描述抛出的异常类型,方便后续的改进。
有多个catch块的时候,需要判断catch的异常间存不存在继承的关系,如果不存在,则catch块之间的排序是没有影响的;如果catch的异常间存在继承的关系,必须保证catch子类的catch块在catch父类的catch块的上方。可以理解为,如果catch父类的catch块先运行了,那么子类catch块将不会有机会被使用,即子类的异常在catch父类的catch块中被处理了。
捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口,使得在控制流转到程序的其它部分以前,能够对程序的状态作统一的管理。实际上finally模块并不是一个必须的模块,很多时候,让程序运行完try/catch模块后,直接运行剩下的代码内容即可。
public class Student {
String studentNo;
int programmingScore;
// 输入学生信息,输入成功返回true;否则返回false
// 可能会遇到的异常:学号输入错误,成绩输入错误
public boolean InputInformation (String studentNo, int programmingScore) throws NoException, ScoreException{
boolean flag;
if (studentNo.matches("[j][p]\\d{10}")) { // 正则表达式判断输入的账号前两位是不是为jp,即后10位为数字
flag = true;
} else {
throw new NoException("英方账号输入错误!");
}
if (programmingScore > 100 || programmingScore < 0) {
flag = false;
throw new ScoreException("学生成绩不应该高于100,或者低于0!");
} else {
flag = true;
}
return flag;
}
public static void main(String[] args) {
Scanner ip = new Scanner(System.in);
Student s = new Student();
s.studentNo = ip.next();
s.programmingScore = ip.nextInt();
try {
System.out.println("Input student information now!");
s.InputInformation(s.studentNo, s.programmingScore);
System.out.println("Input information successfully!");
} catch (NoException ne) {
System.out.println("Please input reasonable student number again!");
} catch (ScoreException sc) {
System.out.println("Please input reasonable student programming score again!");
}
}
}
class NoException extends Exception {
NoException(String s) {
System.out.println(s);
}
}
class ScoreException extends Exception {
ScoreException(String s) {
System.out.println(s);
}
}
输入:ab2222 95
输出:
Input student information now!
英方账号输入错误!
Please input reasonable student number again!