java基础进阶-day29(API异常)
API&异常
- 包装类
- 基本类型包装类
- Integer类
- 自动拆箱和自动装箱(理解)
- int和String类型的相互转换
- 字符串数据排序案例
- 递归
- 递归
- 递归求阶乘
- 数组的高级操作
- 二分查找
- 冒泡排序
- Arrays
- 异常
- 异常
- 编译时异常和运行时异常的区别
- JVM默认处理异常的方式
- 查看异常信息
- throws方式处理异常
- throw抛出异常
- try-catch方式处理异常
- Throwable成员方法
- 异常的练习
- 自定义异常(应用)
包装类
基本类型包装类
- 基本类型包装类的作用
将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
常用的操作之一:用于基本数据类型与字符串之间的转换 - 基本类型对应的包装类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Integer类
- Integer类概述
包装一个对象中的原始类型int的值 - Integer类构造方法
方法名 | 说明 |
---|---|
public Integer(int value) | 根据 int 值创建 Integer 对象(过时) |
public Integer(String s) | 根据 String 值创建 Integer 对象(过时) |
public static Integer valueOf(int i) | 返回表示指定的 int 值的 Integer 实例 |
public static Integer valueOf(String s) | 返回一个保存指定值的 Integer 对象 String |
- 示例代码
package com.itheima_30;
public class IntegerDemo {
public static void main(String[] args) {
// 根据int值创建Integer对象
Integer i1 = new Integer(100);
System.out.println(i1);
Integer i2 = new Integer("100");
System.out.println(i2);
System.out.println("-------------------");
Integer i3 = Integer.valueOf(100);
System.out.println(i3);
Integer i4 = Integer.valueOf("100");
System.out.println(i4);
}
}
自动拆箱和自动装箱(理解)
- 自动装箱
把基本数据类型转换为对应的包装类类型 - 自动拆箱
把包装类类型转换为对应的基本数据类型 - 示例代码
Integer i = 100; // 自动装箱
i += 200; // i = i + 200; i + 200 自动拆箱;i = i + 200; 是自动装箱
int和String类型的相互转换
- int转换为String
- 转换方式
- 方式一:直接在数字后加一个空字符串
- 方式二:同股票String类静态方法valueOf
- 示例代码
- 转换方式
package com.itheima_30;
public class IntegerDemoTest {
public static void main(String[] args) {
int num = 100;
String s1 = num + "";
System.out.println(s1);
// 方式2
String s2 = String.valueOf(num);
System.out.println(s2);
System.out.println("--------");
}
}
- String转换为int
- 转换方式
- 方式一:先将字符串数字转成Integer,再调用ValueOf()方法
- 方式二:通过Integer静态方法parseInt()进行转换
- 转换方式
- 示例代码
package com.itheima_30;
public class IntegerDemo01 {
public static void main(String[] args) {
String s1 = "100";
Integer i1 = Integer.valueOf(s1);
int i2 = i1.intValue();
System.out.println(i2);
// f方式2
int i = Integer.parseInt(s1);
System.out.println(i);
}
}
字符串数据排序案例
有一个字符串:”91 27 46 38 50“,请写程序实现最终输出结果是:”27 38 46 50 91“
- 代码实现
package com.itheima_30;
import java.util.Arrays;
public class IntegerTest {
public static void main(String[] args) {
// 定义一个字符串
String s = "91 27 46 38 50";
// 把字符串中的数字存储到一个int类型的数组中
String[] strArray = s.split(" ");
int[] arr = new int[strArray.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.parseInt(strArray[i]);
}
// 对int类型进行排序
Arrays.sort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
递归
递归
- 递归的介绍
- 以编程的角度来看,递归指的是方法定义中调用方法本身的现象
- 把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
- 递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算
- 递归的基本使用
package com.itheima_30;
public interface MyFactorialDemo02 {
public static void main(String[] args) {
int sum = getSum(100);
System.out.println(sum);
}
private static int getSum(int i) {
if (i == 1) {
return 1;
} else {
return i + getSum(i - 1);
}
}
}
- 递归的注意事项
- 递归一定要有出口。否则内存溢出
- 递归虽然有出口,但是递归的次数不宜过多,否则内存溢出
递归求阶乘
- 案例需求
用递归求5的阶乘,并把结果再控制台输出 - 代码实现
package com.itheima_30;
public class DiGuiDemo01 {
public static void main(String[] args) {
int result = jc(5);
System.out.println("5的阶乘是:" + result);
}
private static int jc(int n) {
if (n == 1) {
return 1;
} else {
return n * jc(n - 1);
}
}
}
数组的高级操作
二分查找
- 二分查找概述
查找指定元素在数组中的位置时,以前的方式是通过遍历,逐个获取每个元素,看是否是要查找的元素,这种方式当数组元素较多时,查找的效率很低。
二分查找也叫折半查找,每次可以去掉一般的查找的范围,从而提高查找的效率 - 需求
在数组(1,2,3,4,5,6,7,8,9,10)中查找某个元素的位置 - 实现步骤
- 定义两个变量,表示要查找的范围,默认min=0,max=最大索引
- 循环查找,但是min<=max
- 计算出mid的值
- 判断mid位置的元素是否为要查找的元素,如果时直接返回对应索引
- 如果要查找的值在mid的左半边,那么min值不变,max=mid-1,继续下次查找
- 如果要查找的值在mid的右半边,那么max值不变,min=mid+1,继续下次查找
- 当min>max,表示要查找的元素在数组中不存在,返回-1.
- 代码实现
package com.itheima_30;
public class MyBinarySearchDemo {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int number = 8;
int i = binarySearchForIndex(arr, number);
System.out.println(i);
}
private static int binarySearchForIndex(int[] arr, int number) {
// 定义查找范围
int min = 0;
int max = arr.length - 1;
while (min <= max) {
// 计算出中间位置mid
int mid = (min + max) >> 1;
if (arr[mid] > number) {
max = mid - 1;
} else if (arr[mid] < number) {
min = mid + 1;
} else {
return mid;
}
}
return -1;
}
}
- 注意事项
有一个前提条件,数组内的元素一定要按照大小顺序排列,如果没有大小顺序,是不能使用而烦恼查找的。
冒泡排序
- 冒泡排序概述
一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直至所有数据按要求完成排序
如果有n个数据进行排序,总共需要比较n-1次
每一次比较完毕,下一次就会少一个数据参与 - 代码实现
package com.itheima_30;
public class MyBubbleSortDemo02 {
public static void main(String[] args) {
int[] arr = {3, 5, 2, 1, 4};
bubbleSort(arr);
}
private static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
printArr(arr);
}
private static void printArr(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
Arrays
- Arrays的常用方法
方法名 | 说明 |
---|---|
public static String toString(int[] a) | 返回指定数组的内容的字符串表示形式 |
public static void sort(int[] a) | 按照数字顺序排列指定的数组 |
public static int binarySearch(int[] a, int key) | 利用二分查找返回指定元素的索引 |
package com.itheima_30;
import java.util.Arrays;
public class MyArrayDemo {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int i = Arrays.binarySearch(arr, 0);
System.out.println(i);
}
}
- 工具类设计思想
- 构造方法用private修饰
- 成员用public static修饰
异常
异常
- 异常概述
异常就是程序出现了不正常的情况
编译时异常和运行时异常的区别
- 编译时异常
- 都是Exception类及其子类
- 必须显示处理,否则程序就会发生错误,无法通过编译
- 运行时异常
- 都是RuntimeException类及其子类
- 必须显示处理,否则程序就会发生错误,无法通过编译
JVM默认处理异常的方式
- 如果程序出现了问题,我们没有做任何处理,最终JVM会做默认的处理,处理方式有如下两个步骤:
- 把异常的名称,错误原因及异常出现的位置邓信息输出在控制台
- 程序停止执行
查看异常信息
控制台在打印异常信息时,会打印异常类名,异常出现的原因,异常出现的位置
我们调bug时,可以根据提示,找到异常出现的位置,分析原因,修改异常代码
throws方式处理异常
- 定义格式
public void 方法() throws 异常类名{
}
- 示例代码
package com.itheima_30;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionDemo {
public static void main(String[] args) throws ParseException {
System.out.println("开始");
// method();
method2();
System.out.println("结束");
}
// 编译时异常
public static void method() throws ParseException {
String s = "2022-08-19";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
}
// 运行时异常
public static void method2() throws ArrayIndexOutOfBoundsException{
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
}
}
- 注意事项
- 这个throws格式是跟在方法的括号后面的
- 编译时异常必须要进行处理,两种处理方案:try…catch…或者throws,如果采用throws这种方案,在方法上进行显示声明,将来谁调用这个方法谁处理
- 运行时异常因为在运行时才会发生,所以在方法后面可以不写,运行时出现异常默认交给JVM处理
throw抛出异常
- 格式
throw new 异常(); - 注意
这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了 - throws和throw的区别
throws | throw |
---|---|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示声明异常,调用该方法有可能会出现这样的异常 | 表示手动抛出异常对象,由方法体内的语句处理 |
- 示例代码
package com.itheima_30;
public class ExceptionDemo8 {
public static void main(String[] args) {
int[] arr = null;
printArr(arr);
}
private static void printArr(int[] arr) {
if (arr == null) {
throw new NullPointerException();
} else {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
}
try-catch方式处理异常
- 定义格式
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
- 执行流程
- 程序从try里面的代码开始执行
- 出现异常,就会跳转到对应的catch里面去执行
- 执行完毕之后,程序还可以继续往下执行
- 示例代码
package com.itheima_30;
public class ExceptionDemo01 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("你访问的数组索引不存在,请回去修改数组索引!");
}
}
}
- 注意
- 如果try中没有遇到问题,怎么执行?
会把try中所有的代码全部执行完毕,不会执行catch里面的代码 - 如果try中遇到了问题,那么try下面的代码还会执行吗?
会直接跳转到对应的catch语句中,try下面的代码就不会再执行了
当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码 - 如果出现的问题没有被捕获,那么程序如何运行?
那么try…catch…就相当于没有写,呢吗也就是自己没有处理,默认交给虚拟机处理 - 同时有可能出现多个异常怎么处理?
处理多个异常,那么就写多个catch就可以了
注意点:如果多个异常之间存在子父类关系,那么父类一定要写再下面
Throwable成员方法
- 常用方法
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
- 示例代码
package com.itheima_30;
public class ExceptionDemo01 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) {
// System.out.println("你访问的数组索引不存在,请回去修改数组索引!");
e.printStackTrace();
}
}
}
异常的练习
- 需求
键盘录入学生的姓名和年龄,其中年龄为18-25岁,超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止 - 实现步骤
- 创建学生对象
- 键盘录入姓名和年龄,并赋值给学生对象
- 如果是非法数据就再次录入
- 代码实现
学生类
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age >= 18 && age <= 25){
this.age = age;
}else{
//当年龄不合法时,产生一个异常
throw new RuntimeException("年龄超出了范围");
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 测试类
public class ExceptionDemo12 {
public static void main(String[] args) {
// 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁,
// 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。
Student s = new Student();
Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名");
String name = sc.nextLine();
s.setName(name);
while(true){
System.out.println("请输入年龄");
String ageStr = sc.nextLine();
try {
int age = Integer.parseInt(ageStr);
s.setAge(age);
break;
} catch (NumberFormatException e) {
System.out.println("请输入一个整数");
continue;
}
/*if(age >= 18 && age <=25){
s.setAge(age);
break;
}else{
System.out.println("请输入符合要求的年龄");
continue;
}*/
}
System.out.println(s);
}
}
自定义异常(应用)
- 自定义异常概述
当java中提供的异常不能满足我们的需求时,我们可以自定义异常 - 实现步骤
- 定义异常类
- 写继承关系
- 提供空参构造
- 提供带参构造
- 代码实现
异常类
package com.itheima_32;
public class AgeOutOfBoundsException extends RuntimeException{
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
学生类
package com.itheima_32;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 18 && age <= 25) {
this.age = age;
} else {
throw new AgeOutOfBoundsException("年龄超出了范围");
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类
package com.itheima_32;
import java.util.Scanner;
public class ExceptionDemo12 {
public static void main(String[] args) {
Student st = new Student();
Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名");
String name = sc.nextLine();
st.setName(name);
while (true) {
System.out.println("请输入年龄");
String ageStr = sc.nextLine();
try {
int age = Integer.parseInt(ageStr);
st.setAge(age);
break;
} catch (NumberFormatException e) {
System.out.println("请输入一个整数");
continue;
} catch (AgeOutOfBoundsException e) {
System.out.println(e.toString());
System.out.println("请输入一个符合范围的年龄");
}
}
System.out.println(st);
}
}