异常处理
两种Java中处理异常的方式
【捕获】 有能力处理你就捕获,自己的问题你就捕获
【抛出】 没有办法处理,或者不是自己的问题,和自己无关,因别人导致的错误,抛出
捕获异常
格式:
try {
// 有可能出现问题的代码,存在一定隐患的代码
} catch (异常类型) {
// 对应当前异常类型的处理方式
// 【因为技术所限,我们只能sout 或者 printStackTrace 后期我们会使用
日志log】
}
``
```java
package com.qfedu.a_exception;
public class Demo1 {
public static void main(String[] args) {
int num1 = 0;
int num2 = 20;
int ret = 0;
/*
* num2 / num1 是存在一定的隐患的,如果num1保存的数据是0,
* 这里会出现一个算术异常
*/
try {
// 有可能出现异常的代码
ret = num2 / num1;
} catch (ArithmeticException e) {
/*
* ArithmeticException 算术异常,catch块中捕获对应异常
* catch大括号内是对应的处理方式,现在只能展示效果
*/
e.printStackTrace();
}
System.out.println(ret);
/*
* java.lang.ArithmeticException: / by zero
* at com.qfedu.a_exception.Demo1.main(Demo1.java:16)
* 0
*/
}
}
-
代码中出现异常,JVM会终止代码运行,如果使用try catch捕获处理异常,JVM会认为当前代码中不存在异常,可以继续运行。
球员受伤,下场处理,处理完毕,回到场上 -
在try大括号内或者catch大括号内都是局部变量,处理操作数据时小心谨慎。
-
try - catch捕获处理异常,可以处理多种异常情况!!!而且建议异常处理分门别类,对症下药
-
代码中存在多种隐患,存在多个异常情况,try - catch捕获有且只能处理第一个出现异常的代码,因为JVM从异常代码开始直接进入异常捕获阶段
-
Exception作为Java中所有异常的超类,在捕获异常处理时如果直接使用Exception进行捕获处理,无法做到异常对症下药操作。
-
Exception可以作为try - catch 最后一个,用于处理其他异常捕获之后没有对症方式遗留问题。[不多见]
抛出异常
关键字:
throw
在方法内特定条件下抛出指定异常
throws
在【方法声明】位置,告知调用者,当前方法有哪些异常抛出
用于处理非当前方法操作问题,导致出现的异常,一般情况下是用于处理方法运行过程中因为参数传入,参数处理,运算结果导致的问题,抛出异常。
throw是一个高级的参数合法性判断!!!
/*
* throws 关键字在方法声明位置告知当前方法的调用者,这里存在异常信息
*/
/**
* 测试方法
*
* @param num1 int类型参数
* @param num2 int类型参数
* @throws ArithmeticException 如果除数为0,当前方法抛出算术异常
*/
public static void test(int num1, int num2)
throws ArithmeticException {
/*
参数合法性判断 之前的方式 low
if (0 == num2) {
System.out.println("你个瘪犊子...坑我");
System.exit(0);
}
*/
// 参数合法性判断,如果num2 为0, 这里存在隐患
if (0 == num2) {
/*
* 存在异常,这里创建一个异常对象抛出,这里构造方法中
* 存在无参数构造方法和有参数构造方法
* 无参数构造方法异常信息为null
* 有参数构造方法可以传入一个String类型数据,异常信息为指定字符串内容
*/
throw new ArithmeticException("除数不能为0");
}
// 如果num2的值为0,num1 / num2 操作是存在隐患的,有问题的
int ret = num1 / num2;
System.out.println(ret);
}
-
代码如果运行到throw抛出异常,之后的代码不再运行,之后的代码是成为无参触及代码
-
代码中存在多种隐患,按照隐含的情况,分门别类处理,不能在同一个条件内抛出两个异常。并且在方法的声明位置,throws之后,不同的异常,使用逗号隔开
-
当调用带有异常抛出的方法时,对于方法抛出的异常,有两种处理方式,可以捕获处理,也可以抛出处理。
异常分类
运行时异常:
RuntimeException 代码运行过程中出现的异常,没有强制处理的必要性
ArrayIndexOutOfBoundsException 数组下标越界异常
NullPointerException 空指针异常
ArithmeticException 算术异常
运行时异常不强制要求捕获和抛出!!!
JVM会处理RuntimeException,也就是告知异常的前因后果!!!
其他异常:
强制要求处理,不管是捕获处理,还是抛出处理,都需要进行操作。
如果未处理!!!直接报错!!!
IDE工具的快速修复
Eclipse Ctrl + 1
IDEA Alt + Enter
自定义异常
KFC
情侣套餐半价…
结果你单身…
业务逻辑存在需求,但是Java中没有合适的异常来描述对应情况,自定义异常
自定义单身狗异常
PFSP
private final static Person
我比较习惯这个顺序 代码中常见的也是这个顺序
自定义异常格式:
class MyException extends Exception {
// 无参数构造方法
public MyException() {}
// 有参数构造方法,且参数数据类型为String类型
public MyException(String message) {
super(message);
}
}
【注意】
Eclipse会提示要求完成一个ID号,可以忽略,存在一个警告,不用管。
package com.qfedu.a_exception;
/*
* 忽略黄色警告!!!
*/
/**
* 自定义异常,单身狗异常
*
* @author Anonymous
*
*/
public class SingleDogException extends Exception {
/**
* 无参数构造方法
*/
public SingleDogException() {}
/**
* 带有参数的构造方法,需要的参数类型是String类型
*
* @param message 异常信息内容
*/
public SingleDogException(String message) {
/*
* 通过super关键字调用父类的参数为String类型构造方法
*/
super(message);
}
}
package com.qfedu.a_exception;
package com.qfedu.a_exception;
public class Demo4 {
public static void main(String[] args) throws SingleDogException {
try {
buyOneFreeOne(false);
} catch (SingleDogException e) {
// TODO Auto-generated catch block
System.out.println("两只黄鹂鸣翠柳,你还是个单身狗");
}
buyOneFreeOne(true);
}
/**
* 买一送一方法,如果有女朋友满足要求,如果没有不满足要求
*
* @param hasGirlFriend boolean类型数据,判断是否有女朋友
* @throws SingleDogException SingleDog 单身狗异常
*/
public static void buyOneFreeOne(boolean hasGirlFriend)
throws SingleDogException {
if (false == hasGirlFriend) { // !hasGirlFriend
// throw 抛出一个异常对象 SingleDogException 自定义异常类
throw new SingleDogException("路见不平一声吼,你还没有女朋友");
}
System.out.println("3RMB 甜筒 买一送一");
}
}
String类
又爱又恨!!!
爱:
字符串基本上就是数据的保存,传输,处理非常重要的一种手段。
恨:
解析过程非常烦人,需要掌握熟记很多方法,同时需要有一定的技巧和灵性
String字符串类型是Java中引用数据类型,并且String类型是使用final修饰,没有自己的子类。
字符串的存储也是非常个性的一件事情,分两种情况,
一种是在内存的数据区
一种是在内存的堆区
字符串是一个常量!!!
字符串确定之后无法修改!!!
package com.qfedu.b_string;
/*
* 字符串常量分析
*/
public class Demo1 {
public static void main(String[] args) {
String str1 = "烤羊排";
String str2 = "烤羊排";
String str3 = new String("烤羊排");
String str4 = new String(str1);
/*
* tfff
* == 等于判断是比较两个变量中保存的数据是否一致
* String str1 str2 str3 str4 都是引用数据类型的变量,也就是==判断比较的是
* str1 ~ str4 中保存的空间首地址
*/
System.out.println("str1 == str2 : " + (str1 == str2)); // true
System.out.println("str2 == str3 : " + (str2 == str3)); // false
System.out.println("str3 == str4 : " + (str3 == str4)); // false
System.out.println("str4 == str1 : " + (str4 == str1)); // false
System.out.println("----------------------------------------");
/*
* 字符串如何比较是否一致???
*
* Java中规定,字符串比较要求采用equals方法来完成,并且使用的equals方法是String类
* 重写Object类内的方法,比较方式是比较字符串内容。
*/
System.out.println("str1.equals(str2) : " + str1.equals(str2)); // true
System.out.println("str2.equals(str3) : " + str2.equals(str3)); // true
System.out.println("str3.equals(str4) : " + str3.equals(str4)); // true
System.out.println("str4.equals(str1) : " + str4.equals(str1)); // true
}
}
获取方法
int length();
获取字符串的长度
char charAt(int index);
从字符串中获取对应下标位置的字符,(存在下标越界问题)
int indexOf(char ch);
找出指定字符在当前字符串中的下标位置
“ABCDEFGABCDEFG”
查询 ‘E’ ==> result 4
int indexOf(String str);
找出指定字符串在当前字符串中的下标位置
“ABCDEFGABCDEFG”
查询 “DE” ==> result 3
int lastIndexOf(char ch);
找出指定字符最后一次出现的下标位置
“ABCDABCD”;
查询 ‘B’ ==> result 5
int lastIndexOf(String str);
找出指定字符串最后一次出现的下标位置
“ABCDABCD”;
查询 “CD” ==> result 6
判断方法
boolean endsWith(String str);
判断当前字符串是不是指定字符串结尾,如果是返回true,不是返回false
boolean startsWith(String str);
判断当前字符串是不是指定字符串开始,如果是返回true,不是返回false
boolean isEmpty();
判断当前字符串是否为空,空字符串是指 “” 双引号什么都没有
boolean contains(String str) 是否包含指定序列 应用:搜索
判断该指定字符串是否是当前字符串的子字符串。
当前字符串:
“ABCDEFG”;
参数字符串:
“CDE”; ==> result true;
参数字符串:
“CE”; ==> result false
原码是调用String类的indexOf方法,找出指定字符串的下标位置,indexOf方法下标为大于等于0,返回 true,否则返回 false
boolean equals(Object anObject);
重写 Override Object类内方法,判断两个字符串是否一致。
boolean equalsIgnoreCase(String anotherString);
忽略大小写是否相等,不考虑英文大小写方式比较两个字符串是否一致。
转换方法
String(char[] value);
将字符数组转换为字符串
String(char[] value, int offset, int count);
将字符数组转换为字符串,从指定offset位置开始,计数count
offset是开始位置
count是截取个数
例如:
char[] arr = {‘A’, ‘B’, ‘C’, ‘D’, ‘E’};
调用方法参数:
new String(arr, 2, 3); ==> result “CDE”
static String valueOf(char[] data);
同理String(char[] value);
tips: 底层代码是 return new String(data);
static String valueOf(char[] data, int offset, int count);
同理String(char[] value, int offset, int count);
tips: 底层代码是 return new String(data, offset, count);
char[] toCharArray();
将字符串转换为字符数组
例如:
“ABCDE”;
返回值:
{‘A’, ‘B’, ‘C’, ‘D’, ‘E’};
其他方法
String replace(char oldChar, char newChar);
替换使用newChar字符类型,替换当前字符串内的所有指定字符oldChar
例如:
“ABCDEABCDE”;
调用方法:
“ABCDEABCDE”.replace(‘A’, ‘你’);
返回值结果:
“你BCDE你BCDE”; 【注】原字符串不变
String[] split(String regex); 【重点】
【重点】切割,将当前字符串按照指定字符串切割成String类型数组
例如:
String str = “你好!他好!大家好!广州好迪”;
调用方法:
str.split("!");
返回值结果:
String[] arr = {“你好”, “他好”, “大家好”, “广州好迪”};
调用方法:
str.split(“好”);
返回值结果:
String[] arr = {“你”, “!他”, “!大家”,"!广州", “迪”};
String substring(int beginIndex); 【重点】
从指定beginIndex开始,到字符串结尾截取字符串
例如:
String str = “ABCDEFG”;
调用方法:
str.substring(3);
返回值结果:
“DEFG”
String substring(int beginIndex, int endIndex); 【重点】
从指定beginIndex开始,到endIndex结束,截取字符串
要头不要尾 beginIndex <= 结果范围 < endIndex [3,5)
例如:
String str = "ABCDEFG";
调用方法:
str.substring(3, 5);
返回值结果:
"DE"
String toUpperCase();
字符串中所有的英文字母转大写,返回新字符串
String toLowerCase();
字符串中所有的英文字母转小写,返回新字符串
String trim();
去除字符串两边的空格