目录
1.异常基本概念:
Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法
错误和逻辑错误不是异常)
1.1 error
Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError[栈溢出]和OOM(out of memory),Error 是严重错误,程序会崩溃。
1.2 exception
其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception 分为两大类:运行时异常]和编译时异常[]。
2.五大异常类
常见的运行时异常包括
- NullPointerException空指针异常
- ArithmeticException数学运算异常
- ArraylndexOutOfBoundsException数组下标越界异常
- ClassCastException类型转换异常
- NumberFormatException数字格式不正确异常[]
2.1空指针异常
当应用试图在需要对象的地方使用null时,就会抛出空指针异常
2.2数学运算异常
当出现异常的运算时,抛出此异常
2.3数组下标越界异常
数组下标越界异常,数组下角标超出数组大小,就会抛出此异常
2.4类型转换异常
试图将对象强制转换为不是该实例的子类时(向下转型)
2.5数字格式不正确异常[]
当应用程序将字符串转换为一种数值类型,但该字符串不能转成适当形式,就会抛出该异常
3.异常处理机制
异常处理机制
1.try-catch-finally(),finally一般是释放资源
2.throws,抛出异常给上一级(谁调用谁处理,最顶级是jvm机)
3.1 try-catch-finally
try{ //尝试执行下面的代码 //order 1(可能会有异常) }catch(ExceptionType1 Re1){ //如果捕获种类为 类型1的异常 //order 2() //业务逻辑2 }catch(ExceptionType2 Re2){ //如果捕获种类为 类型2的异常 //order3() //业务逻辑3 } //...多个分支 //finally 部分可以没有 finally{ //无论是否捕获异常,都执行 //order N //一般为垃圾分解,资源释放 }
- 如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块.
- 如果异常没有发生,则顺序执行try的代码块,不会进入到catch.
- 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,放资源等),则使用如下代码-finally{}
- 可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception 在后,NullPointerException 在前),如果发生异常,只会匹配一个catch
3.2 throws
- 如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理(扔给上一级调用者,最顶级是JVM机)。
- 在方法声明中用throws语句 可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
3.3 异常处理
- 对于编译异常,程序中必须处理,比如try-catch 或者throws
- 对于运行时异常,程序中如果没有处理,默认就是throws的方式处理(即在调用异常方法的方法后面标注throws 异常)
- 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型[举例]
- 在throws 过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws
4.自定义异常
4.1 throw
用于在方法中抛出异常 ,手动生成异常
throw new 异常类 throw 异常类的实例对象
5. throws 和 throw
意义 | 位置 | 后面跟的 | |
---|---|---|---|
throws | 异常处理的一种方式 | 方法声明处 | 异常类 |
throw | 手动生成异常 | 方法体中 | 异常类对象实例 |
6.实例
6.1目的
生成一个 2-36进制的进制转换方法
要求:
- 输入字符串,能从任意进制转换到任意进制
- 能够识别输入的进制大小,并能抛出异常,并且要求重新输入直到符合要求为止
- 能够识别字符串中超出进制的位,并且指出,抛出异常,修改原进制或修改字符串,并且要求重新输入直到符合要求为止
- 能够识别出错误字符,并且指出,抛出异常,并且要求重新输入直到符合要求为止
6.2. 创建异常:
- CountsBoundException:进制范围异常
- StrDisTransferException :字符串无法转换异常
class CountsBoundException extends RuntimeException{
public CountsBoundException(String message) {
super(message);
}
}
class StrDisTransferException extends RuntimeException{
//指出是那种原因 message
//指出是哪位发生了异常
int Index;
public StrDisTransferException (String message,int index) {
super(message);
this.Index = index;
}
}
6.3. 创建静态方法:
声明部分:
定义部分:
// 与main 方法在一个类中:
public static String toString_(String inputstr,int InputCount,int OutputCount)throws CountsBoundException,StrDisTransferException{
// 能够识别输入的进制大小,并能抛出异常
if(InputCount < 2 || InputCount > 36){
throw new CountsBoundException("InputCountException");
}
if(OutputCount < 2 || OutputCount > 36){
throw new CountsBoundException("OutputCountException");
}
String str = new String();
int sum = 0;
//指针指向字符串末尾
int index = inputstr.length() - 1;
//转成十进制
while(index >= 0){
//幂
int power = inputstr.length() - 1 - index;
//获取字符(转换为ascii码)
int strx = (int)inputstr.charAt(index);
//0-9
if(strx >= 48 && strx<=57){
strx -= 48;
}
//A-Z (10-35)
else if(strx >= 65 && strx<= 90){
strx -= 55;
}
//a-z (10-35)
else if(strx >= 97 && strx<= 122){
strx -= 87;
}
//最后一个负号
else if(index == 0 && strx == 45){
strx = 0;
sum = -sum;
}
else{
throw new StrDisTransferException("StrException",(power+1));
// return inputstr+"中混入了奇怪的字符";
}
//检查进制不符合
if(strx >= InputCount){
throw new StrDisTransferException("DataException",(power+1));
// return "第"+(index+1)+"位"+"进制错误"+"( "+inputstr.charAt(index)+" )";
}
//和相加
sum += strx * Math.pow(InputCount,power);
//指针左移
index--;
}
//计算S2进制的字符串
int[] value= new int[64];
//保留符号
int sign = (int)Math.signum(sum);
sum = Math.abs(sum);
int diff = OutputCount;
byte time = 0; //确定最高次幂
while (sum/diff > 0) {
diff *= OutputCount; //diff = S2^(t+1)
time++;
}
//计算幂
diff /= OutputCount;
//第一个0次幂,第二个一次幂,以此类推...
index = time;
while (index >= 0) {
value[index] = sum/diff;
sum = sum%diff;
diff /= OutputCount;
index--;
}
index = time ;
// 得到字符串长度 (index)
// 从最后一位到第一位进行转换
char str0 = '0';
while(index >= 0){
if (value[index] >=0 && value[index] <=9){
str0 = (char)(value[index] + 48);
}
else if(value[index] >=10 && value[index] <=35){
str0 = (char)(value[index] + 87);
}
str = str + str0;
index--;
}
if(sign == -1){
str = '-' + str;
}
return str;
}
6.4 方法调用
public static void main(String[] args) {
String inputstr ="ffgf";
int InputCount = 16;
int OutputCount = 2;
while(true){
try{
System.out.println("Result is : "+ toString_(inputstr,InputCount,OutputCount)
+ "(" + OutputCount + ")" //进制
+ "{" +toString_(inputstr,InputCount,10)+"(10)}");
//如果成功运行则 break;
break;
//如果进制输入过大或过小
}catch(CountsBoundException cbe){
if(cbe.getMessage() == "InputCountException"){
System.out.println( "InputCountException" +" :\n"
+ "Please input a number (which is more than '2' but less than '36')");
java.util.Scanner scanner= new java.util.Scanner(System.in);
InputCount = scanner.nextInt();
}else if(cbe.getMessage() == "OutputCountException"){
System.out.println( "OutputCountException" +" :\n"
+ "Please input a number (which is more than '2' but less than '36')");
java.util.Scanner scanner= new java.util.Scanner(System.in);
OutputCount = scanner.nextInt();
}
}catch (StrDisTransferException sde){
if(sde.getMessage() == "StrException"){
//获取字符串异常位置:
int index = inputstr.length() - sde.Index ;
//指引输入的提示文字
System.out.println("StrException"+" : \n"
+ "Please raplace the char:\"" + inputstr + "(" + InputCount
+")\"["+sde.Index+"]:\""+inputstr.charAt(index)+"\"-> ?");
//输入改变的字符
java.util.Scanner scanner2 = new java.util.Scanner(System.in);
char replaceChar = scanner2.next().charAt(0);
inputstr = inputstr.replace(inputstr.charAt(index),replaceChar);
//输出的提示文字
System.out.println("new Str is "+ inputstr + "(" + InputCount + ")");
}
else if(sde.getMessage() == "DataException"){
//获取字符串异常位置:
int index = inputstr.length() - sde.Index ;
//指引输入的提示文字
System.out.println("DataException"+": \"" + inputstr + "(" + InputCount
+ ")\"["+sde.Index+"]:\""+inputstr.charAt(index)+"\" may be wrong");
//指引输入的提示文字
System.out.println("Please select to change oldSystem(1) or String(2)?");
//输入选择 1or2
java.util.Scanner scanner = new java.util.Scanner(System.in);
String select = scanner.next();
char decision = select.charAt(0);
while(select.length() == 1){
//如果选择改变字符串
if(decision == '2'){
//指引输入的提示文字
System.out.println("DataException" + " :\n" +
"Please raplace the char:\"" + inputstr + "(" + InputCount
+ ")\"["+sde.Index+"]:\""+inputstr.charAt(index)+"\"-> ?");
//输入改变的字符
java.util.Scanner scanner2= new java.util.Scanner(System.in);
char replaceChar = scanner2.next().charAt(0);
inputstr = inputstr.replace(inputstr.charAt(index),replaceChar);
//输出的提示文字
System.out.println("new Str is "+ inputstr + "(" + InputCount + ")");
break;
}else if(decision == '1'){
int mincount = (int)inputstr.charAt(index);
//计算允许的最小进制
//0-9
if(mincount >= 48 && mincount<=57){
mincount -= 48;
}
//a-z (10-35)
else if(mincount >= 97 && mincount<= 122){
mincount -= 87;
}
//指引输入的提示最小进制
System.out.println("Please input a number (which is more than " + "\'"+ (mincount+1) + "\'"+" but less than '36')");
//输入改变的字符进制
java.util.Scanner scanner2= new java.util.Scanner(System.in);
InputCount = scanner2.nextInt();
//输出的提示文字
System.out.println("new InputCounts is "+ inputstr+"(" + InputCount + ")");
break;
}
}
}
}
//满足要求跳出循环
}
}