一、关于异常的练习
package com.exercise.trycatch;
import java.util.Scanner;
/**
* @author alice_huijing
* @version 1.0
*/
public class TryCatchExercise01 {
}
// 第一道题
//class Exception01 {
// public static int method() {
// try {
// String[] names = new String[3]; // names指向了一个数据,但是里面为空null
// if (names[1].equals("tom")) { // null. 出现空指针异常,会在3捕获
// System.out.println(names[1]);
// } else {
// names[3] = "hspedu";
// }
// return 1;
// } catch (ArrayIndexOutOfBoundsException e) {
// return 2;
// } catch (NullPointerException e) { // 捕获,这里只是捕获了,但是并不会返回
// return 3;
// } finally { // 但是finally是必须执行的,所以必须会执行finally下面的语句,返回4
// return 4;
// }
// }
// public static void main(String[] args) {
// System.out.println(method()); // 4
// }
//}
// 第二道题
//class Exception02 {
// public static int method() {
// int i = 1;
// try {
// i++; // i等于2
// String[] names = new String[3]; // names->null null null
// if (names[1].equals("tom")) { // 空指针异常,下方代码不会执行
// System.out.println(names[1]);
// } else {
// names[3] = "hspedu";
// }
// return 1;
// } catch (ArrayIndexOutOfBoundsException e) {
// return 2;
// } catch (NullPointerException e) { // 执行空指针异常的代码先加之后返回,i等于3,因为finally必须要执行不会返回
// return ++i;
// } finally {
// return ++i; // 先加,i等于4,然后返回4
// }
// }
// public static void main(String[] args) {
// System.out.println(method()); // 4
// }
//}
// 第三题
//class ExceptionExe01 {
// public static int method() {
// int i = 1;
// try {
// i++; // i等于2
// String[] names = new String[3]; // names -> null,null,null
// if (names[1].equals("tom")) { // null. 空指针异常
// System.out.println(names[1]);
// } else {
// names[3] = "hspedu";
// }
// return 1;
// } catch (ArrayIndexOutOfBoundsException e) {
// return 2;
// } catch (NullPointerException e) { // i等于3,返回3,底层保存在一个临时变量temp中,继续往下执行finally,最后回来返回
// return ++i;
// } finally {
// ++i; // 必须要执行,i等于4
// System.out.println("i="+i); // i=4
// }
// }
// public static void main(String[] args) {
// System.out.println(method()); // 3
// }
//}
/*
try-catch异常处理
try-catch-finally执行顺序小结
1、如果没有出现异常,则执行try块中所有的语句,不执行catch块中的语句,如果有finally,最后还要继续执行finally里面的语句
2、如果出现异常,则try块中异常发生后,剩下的语句不再执行。将执行catch块中的语句,如果有finally,最后还要执行finally里面的语句。
课后练习题:如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止。
将输入的字符串转换成整数,如果不能转换就是产生了异常,捕获然后处理即可。
思路分析:
1、创建一个Scanner对象
2、使用无限循环,去接收一个输入
3、然后将该输入的值,转换成一个int
4、如果在转换的时候,抛出异常,说明输入的内容不是一个可以转换成int的内容
5、如果没有抛出异常,则break,该循环。
*/
class Test {
public void TryCatch() {
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while (true) {
System.out.print("请输入一个整数:");
inputStr = scanner.next();
try {
num = Integer.parseInt(inputStr); // 这里可能会抛出异常
break;
} catch (NumberFormatException e) {
System.out.println("你输入的不是一个整数!!");
}
}
System.out.println("你输入的是->" + num);
}
}
二、throws异常处理
package com.exercise.trycatch;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* @author alice_huijing
* @version 1.0
*/
public class Throws02 {
public static void main(String[] args) {
}
public void f1() throws FileNotFoundException {
// 创建一个文件对象,因为这里是一个编译异常,所以这里需要明确的处理。可以使用try catch处理,或者是抛出
// 让谁处理?使用throws抛出异常,让调用f1方法的调用者来进行处理。
FileInputStream fis = new FileInputStream("d://aa.txt"); // 这是一个编译时异常
// 并且因为Exception是FileNotFoundException的父类,也可以抛出的是Exception
//throws关键字后面也可以是一个异常列表,即抛出多个异常,异常之间使用逗号分割
//FileNotFoundException,NullPointerException,当然,因为这三个异常都是Exception的子类,所以只写
//Exception都可以抛出
}
}
/*
throws异常处理
基本介绍
1、如果一个方法中的语句执行时可能生成某种异常,但是并不能确定如何处理这种异常,则此方法因显示地声明抛出异常,表示该方法将
不对这些异常进行处理,而该方法的调用者负责处理。
2、在方法声明中使用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
*/
package com.exercise.trycatch;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* @author alice_huijing
* @version 1.0
*/
public class Throws03 {
public static void main(String[] args) {
}
public void f2() {
// 2、对于运行时异常,程序中如果没有处理,默认就是throws的方式来处理
int n1 = 10;
int n2 = 0;
double res = n1 / n2;
// 我们自己是知道这里存在算术异常的,但是这里好像爆红,其实默认是使用throws的方式来进行了处理相当于
// public void f2() throws ArithmeticException,默认这边是有这样一句话
// 我们怎么知道确实是有这样一句话呢?
// 当我们在main中调用f2的时候实际上这里会将异常抛出给到main,而
// 在main中相当于也是默认有这样的一句话throws ArithmeticException
// 最终抛给JVM,而JVM就不会有捕获这样的操作,JVM直接简单粗暴的将你的程序挂掉
}
public static void f1() throws FileNotFoundException {
// 这里直接调用f3()会报错
// 1、因为f3这个方法抛出的是一个编译异常必须要求处理
// 2、这个时候就需要处理这个异常,可以捕获这个异常或者是继续抛出这个异常
f3();
// try {
// f3();
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
}
public static void f3() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("d://aa.txt");
}
public static void f4() {
// 这里调用f5是可以的
// 因为f5是一个运行异常的抛出
// 在java中运行异常不强制要求处理,所以有默认处理机制
// 相当于f4这里默认抛出throws ArithmeticException
f5();
}
public static void f5() throws ArithmeticException {
}
}
/*
throws异常处理的注意事项和使用细节
1、对于编译异常,程序中必须要处理,比如try-catch或者throws来处理
2、对于运行时异常,程序中如果没有处理,默认就是throws的方式来处理
3、子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致
要么为父类抛出的异常的类型的子类型
4、在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws
*/
class Father {
public void method() throws RuntimeException {
}
}
class Son extends Father {
@Override
public void method() throws NullPointerException {
/*
子类重写了父类的方法,对抛出的异常的规定,子类重写的方法,
所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
*/
}
}
三、自定义异常
package com.exercise.trycatch;
/**
* @author alice_huijing
* @version 1.0
*/
public class Customize04 {
public static void main(String[] args) {
int age = 180;
// 要求范围在18-120之间,否则抛出一个自定义异常
if (!(age >= 18 && age <= 120)) {
// Exception in thread "main" com.exercise.trycatch.AgeException: 年龄需要在18~120之间
throw new AgeException("年龄需要在18~120之间");
}
System.out.println("你的年龄范围正确。");
}
}
// 自定义一个异常
// 一般情况下我们自定义异常都是继承运行时异常
// 将自定义异常做成运行时异常,好处是,我们可以使用默认的处理比较方便
// 如果继承的是Exception,那么就是一个编译异常,不是不可以,如果继承的是这个,那么
// 我们在main中调用的时候main上面也需要显示的写throws AgeException,因为编译异常需要要求程序员处理
// 没有默认的,而运行时异常有默认的更加方便。
class AgeException extends RuntimeException {
public AgeException(String message) {
// 可以通过构造器设置内容
super(message);
/*
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
最终到达detailMessage,最终将异常输出出来
*/
}
}
/*
自定义异常
基本概念
当程序中出现了某些错误,但是该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,
用于描述该错误信息。
自定义异常的步骤
1、定义类:自定义异常类名(程序员自己写)需要继承Exception或者是RuntimeException
2、如果继承Exception,属于的是编译异常
3、如果继承RuntimeException属于运行异常(一般来说,继承RuntimeException)
*/
四、throw和throws的区别
package com.exercise.trycatch;
/**
* @author alice_huijing
* @version 1.0
*/
public class throwAndThrows05 {
// public static void main(String[] args) {
//
// }
}
/*
throw和throws的区别
throws的意义:异常处理的一种方式
位置:方法声明处
后面跟的东西:异常类型
throw的意义:手动生成异常对象的关键字
位置:方法体中
后面跟的东西:异常对象
*/
class ReturnExceptionDemo {
static void methodA() {
try {
System.out.println("进入方法A");
throw new RuntimeException("制造异常"); // 被调用这个方法的调用者捕获
} finally {
System.out.println("使用A方法的finally");
}
}
static void methodB() {
try {
System.out.println("进入方法B");
return ; // 不会马上执行,finally先执行
} finally {
System.out.println("调用B方法的finally");
}
}
public static void main(String[] args) {
try {
ReturnExceptionDemo.methodA(); // 在这里捕获这个运行时异常
} catch (Exception e) {
System.out.println(e.getMessage()); // 制造异常,这个是异常信息
}
ReturnExceptionDemo.methodB();
}
}
/*
进入方法A
使用A方法的finally
制造异常
进入方法B
调用B方法的finally
*/
五、练习
package com.exercise.trycatch;
/**
* @author alice_huijing
* @version 1.0
*/
public class Homework06 {
public static void main(String[] args) {
try { // 将可能会产生异常的代码块进行包裹
if (args.length != 2) {
throw new ArrayIndexOutOfBoundsException("参数个数不正确。");
} // 1.因为要接收命令行的是两个参数,限定,这里可能会抛出第一个异常
// 2将接收到的两个字符串转换成整数,因为当前数组是String[] args,这里可能不能转换也会抛出一个异常
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
// 3接下来是计算,可能产生除零的异常
double res = cal(n1, n2);
System.out.println("结算结果是="+res);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
} catch (NumberFormatException e) {
System.out.println("参数格式不正确,需要输入整数");
} /*这里有一个异常IDEA检测不到,就是这里的除零的异常,所以无法自动生成*/
catch (ArithmeticException e) {
System.out.println("出现了除0的异常");
}
}
public static double cal(int n1, int n2) {
return n1 / n2; // 除零出现异常自动往上面丢
}
}
// 第一题
/*
1、编写应用程序EcmDef.java,接收命令行的两个参数(整数),计算两数相除。
2、计算两个数相除,要求使用方法cal(int n1, int n2)
3、对数据格式不正确,缺少命令行参数,除以0进行异常处理。
*/
package com.exercise.trycatch;
/**
* @author alice_huijing
* @version 1.0
*/
/*
说出以下代码是否会发生异常,如果会,是哪种异常?如果不会则打印结果是什么
// 这里可能会报一个越界ArrayIndexOutOfBoundsException
if (args[4].equals("john")) {
System.out.println("AA");
}else {
System.out.println("BB");
}
Object o = args[2]; // 这里的编译类型是Object,这里的运行类型是String,当前指向String
Integer i = (Integer)o; // 按理来说应该要转换成为String,但是这里转换成为Integer,Integer和String没有什么关系,出现
// ClassCastException
*/
/*
写出程序结果
B
C
D
*/
//public class Homework07 {
// public static void func() {
// try {
// throw new RuntimeException(); // 抛出一个运行时异常RuntimeException
// } finally {
// System.out.println("B"); // finally这里还是要输出
// }
// }
// public static void main(String[] args) {
// try {
// func(); // 运行时候异常默认丢到调用的地方
// System.out.println("A"); // 上面产生了异常,这行代码不会再执行
// }catch(Exception e) {
// System.out.println("C"); // 捕获运行时异常,输出C
// }
// System.out.println("D"); // 异常得到捕获,所以程序不会结束,正常输出
// }
//}
/*
写出程序结果
B
C
D
*/
public class Homework07 {
public static void main(String[] args) {
try {
showExce(); // 接收到抛出的异常,这里进行捕获
System.out.println("A"); // 后面的这个代码不会被执行
} catch (Exception e) {
System.out.println("B"); // 捕获到Exception异常进行处理
} finally {
System.out.println("C"); // 不管是否有异常都要执行
}
System.out.println("D"); // 因为捕获了异常所以程序不会结束,这条语句被输出
}
public static void showExce() throws Exception { // 因为Exception是编译时异常,需要手动抛出
throw new Exception();
}
}
六、包装类
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useclass01 {
public static void main(String[] args) {
}
}
/*
常用类
这个章节涉及到的内容
包装类
String
StringBuffer
StringBuilder
Math
Date,Calendar,LocalDate...
System
Arrays
BigInteger BigDecimal
一、包装类Wrapper
1、针对八种基本数据类型相应的引用类型-包装类
2、因为有了类,就可以调用类中的方法。
基本数据类型:boolean char byte short int long float double
包装类: Boolean Character Byte Short Integer Long Float Double
其中:Byte Short Integer Long Float Double 的父类是Number
先来看看Boolean的类图
再来看Character
Byte
因为后面这几个的父类也是Number的,就可以写在一起
*/
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useClass02 {
public static void main(String[] args) {
// 1手动装箱
// Integer的装箱
// JDK5以前是手动装箱和拆箱
// 手动装箱,基本数据类型得到包装类型
int n1 = 100;
Integer integer = new Integer(n1); // 第一种方式
Integer integer1 = Integer.valueOf(n1); // 第二种方式
// 2手动拆箱
// 将包装类型得到普通类型
int i = integer.intValue();
// JDK5以及以后
// 就可以自动装箱和自动拆箱了
int n2 = 200;
// 自动装箱
Integer integer2 = n2; // 将基本数据类型直接赋给包装类型
// 底层使用的仍然是Integer.valueOf(n1);
// 自动拆箱同样是直接赋值
int n3 = integer2; // 实际上底层仍然使用的还是这里的intValue()
// 其他包装类的用法类似,这里就不一一的举例
}
}
/*
包装类和基本数据类的转换
包装类
包装类和基本数据类型的转换
演示包装类 和 基本数据类型的相互转换,这里以int和Integer演示。
1、JDK5以前的手动装箱和拆箱的方式,装箱:基本类型->包装类型
反之,拆箱
2、JDK5以后含有JDK5的自动装箱和拆箱方式
3、自动装箱底层调用的是valueOf方法,比如Integer.valueOf()
*/
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useClass03 {
}
/*
包装类的课堂测试题
下面代码是否正确
Double d = 100d; // 自动装箱,底层使用Double.valueOf(100d);
Float f = 1.5f; // 自动装箱, 底层使用Float.valueOf(1.5f);
如下两个题目输出结果是相同的吗,各是什么?
Object obj1 = true?new Integer(1):new Double(2.0);
System.out.println(obj1); //1.0,因为前面三元运算符中精度最高的部分是double,所以精度会提升到double
// 也就是三元运算符要看作一个整体。
Object obj2;
if(true) obj2 = new Integer(1);
else obj2 = new Double(2.0);
System.out.println(obj2); // 1,这里和三元运算符不一样,是分开来运算的。
*/
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useClass04 {
public static void main(String[] args) {
// 包装类Integer->String
Integer i = 100; //自动装箱 int -> Integer
// 方式1
String str1 = i + ""; // i还是Integer没有变,只是产生了一个新的对象给str1,Integer->String
// 方式2
String str2 = i.toString();
// 方式3
String str3 = String.valueOf(i);
// 将String转换成包装类
String str4 = "12345";
Integer i2 = Integer.parseInt(str4); // 这边其实返回的是一个int类型,但是因为有自动装箱还可以转为Integer
// 方式二可以使用构造器
Integer i3 = new Integer(str4); // 构造器f
// 常用的方法
System.out.println(Integer.MIN_VALUE); // 返回类型支持的最小值
System.out.println(Integer.MAX_VALUE); // 返回类型支持的最大值
System.out.println(Character.isDigit('a')); // 判断是不是数字
System.out.println(Character.isLetter('a')); // 判断是不是字母
System.out.println(Character.isUpperCase('a')); // 判断是不是大写
System.out.println(Character.isLowerCase('a')); // 判断是不是小写
System.out.println(Character.isWhitespace('a')); // 判断是不是空格
System.out.println(Character.toUpperCase('a')); // 转成大写
System.out.println(Character.toLowerCase('A')); // 转小写
}
}
/*
包装类型和String类型的相互转换WrapperVSString.java
*/
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
/*
看一道面试题,输出的什么结果,为什么
*/
public class useClass05 {
public static void main(String[] args) {
new AA().method1();
}
}
class AA {
public void method1() {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); // 判断对象,两个对象使用==判断对象是不是同一个false
Integer m = 1; // 底层使用Integer.valueOf(1);
Integer n = 1; // 在-128到127就是直接返回,不会new,所以是true
System.out.println(m == n); // 看看底层代码是怎么写的,不能判断是不是new出来的,这里为true
// 也可以看源码中的IntegerCache.cache这个数组,其实已经创建好了。
Integer x = 128; // 128了不再范围中,需要new,所以这里为false
Integer y = 128;
System.out.println(x == y);
/*
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
取决i是多少,这个范围是关键,
可以看源码中的注释
“This method will always cache values in the range -128 to 127,”
或者继续追low和high就能看到了。
*/
}
}
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useClass06 {
public static void main(String[] args) {
/*
public Integer(int value) {
this.value = value;
}
*/
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2); //通过new的方式创建对象,不是同一个对象,false
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4); // false
/*
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
-128 to 127
*/
Integer i5 = 127;
Integer i6 = 127;
System.out.println(i5 == i6); // 不是通过new的方式,所以是同一个对象
Integer i7 = 128;
Integer i8 = 128;
System.out.println(i7 == i8); // 超过了了127了,所以通过的是new创建对象,所以不是同一个对象。
Integer i9 = 127;
Integer i10 = new Integer(127); // 使用了new
System.out.println(i9 == i10);
Integer i11 = 127;
int i12 = 127;
System.out.println(i11 == i12); // 只要有一个是基本数据类型就是判断的值是否相等。
Integer i13 = 128;
int i14 = 128;
System.out.println(i13 == i14); // 只要有一个是基本数据类型就判断的值是否相等。
}
}
/*
Integer类的面试题总结
看看下面代码,输出什么结果。
*/
七、附图
![image]()