这里将自己学习java及其应用的一些笔记、积累分享一下,如果涉及到了文章、文字侵权,请联系我删除或调整。
一、异常
1.1 概述
- 异常:封装错误信息的对象
- 错误信息:
类型
提示消息
行号
1.2 异常的继承结构
Throwable
|- Error 系统级错误
|- Exception 异常,可修复的错误
|- 其他Exception
|- RuntimeException
|- NullPointerException
|- ArrayIndexOutOfBoundsException
|- ArithmeticException
|- NumberFormatException
|- ClassCastException
|- ClassNotFoundException
|- ...
1.3 异常捕获
下面介绍3中常见的异常捕获的代码结构:
-
第一种:
try {
} catch(AException e){
……
} catch(BException e) {
……
} catch(父类型Exception e) {
……
} finally {
不管出错还是不出错都会执行。一般在此,会做一些资源管理的操作,防止资源泄露。
finally 不论是否有break,reutrn等语句,它都会执行
}
-
第二种:
try {
} catch() {
……
}
-
第三种:
try {
} finally {
……
}
1.4 练习:异常-异常捕获
package 异常;
import java.util.Scanner;
public class Test1_trycatch {
public static void main(String[] args) {
while (true) {
// 捕获异常
try {
f();
break;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("索引越界了,请输入两个整数!");
} catch (NumberFormatException e) {
System.out.println("输入数据格式有误!");
} catch (ArithmeticException e) {
System.out.println("0不能作除数!");
} catch (Exception e) {
System.out.println("索引没越界,输入数据格式也对,0也没做除数,可是就是有问题,你气不气!");
} finally {
// 一般做一些资源管理,防止资源泄露
// finally 不论是否break,reutrn等都会执行
System.out.println("Finally被执行了!");
}
}
}
private static void f() {
/*
* "345,543"拆分 => ["345","543"] 0 1 分别将下标1与下标2解析为整数并相除
*/
System.out.println("输入两个整数,例如格式345,543:");
String s = new Scanner(System.in).nextLine();
String arr[] = s.split(",");
int n1 = Integer.parseInt(arr[0]);
int n2 = Integer.parseInt(arr[1]);
int r = n1 / n2;
System.out.println(r);
}
}
二、throws
2.1 概述
-
throws用于在方法上设置异常的抛出管道,例如:
void f() throws X,Y,Z {
}
- 所有方法上都有默认的异常管道:RuntimeException
2.2 练习:thows
package 异常;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;
public class Test2_throws {
// throws设置管道
public static void main(String[] args){
try {
f();// f()也会进一步throw解析异常与IO异常,也需捕获或设置管道
} catch (ParseException e) {
System.out.println("日期格式输出!");
e.printStackTrace();// 打印完整异常信息
} catch (IOException e) {
System.out.println("无法创建文件!");
e.printStackTrace();
}
}
private static void f() throws ParseException, IOException {
/*
* 输入一个字符串日期 依据字符串"2019-3-16"得到日期毫秒值
*
* 1.将字符串变成Date对象, SimpleDateFormat转变对象 .parse("2019-3-16"),解析为毫秒值;
*/
System.out.println("输入日期(年-月-日):");
String s = new Scanner(System.in).nextLine();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dec = sdf.parse(s);// 会抛一个解析异常,需要管道或捕获
long t = dec.getTime();
File f = new File("d:/" + t + ".txt");
f.createNewFile();// 会抛一个IO异常,需要管道或捕获
}
}
三、catch和throws
3.1 概述
- 异常处理只有两种方式: catch 和 throws
- 异常处理,必须二选一
- Java语法,强制开发者事先考虑异常如何处理
- 刚接触软件开发的初学者,可能会捕获,但不处理异常
try {
...
} catch(Exception e) {
}
3.2 catch 和 throws怎么选(很多博文、大佬文章都聊过这个话题)
底层异常,建议应该向前抛到前面处理
经验少时,不知道该在什么位置捕获处理,应该选择 throws
四、throw
4.1 概述
- throw:人为手动抛出异常,执行异常的抛出动作
- throw 可类比成 return
if(逻辑错误) {
AException e = new AException("提示消息");
throw e;
}
4.2 练习:throw
package 测试throw;
import java.util.Scanner;
public class Test3 {
public static void main(String[] args) {
f();
}
private static void f() {
/*
* 23.25/0 Infinity
*/
System.out.println("输入两个浮点数:");
double a = new Scanner(System.in).nextDouble();
double b = new Scanner(System.in).nextDouble();
try {
double r = divide(a, b);
System.out.println(r);
} catch (ArithmeticException e) {
System.out.println("不能除0!");
//e.printStackTrace();//打印完整异常
}
}
private static double divide(double a, double b) {
if(b == 0) {
ArithmeticException e = new ArithmeticException("/ by zero");
throw e; //return e;
}
return a/b;
}
}
五、异常包装
5.1 概述
- 将捕获的异常,包装成另一种类型,再抛出
try {
……
} catch(AException e) {
throw new BException(e);
}
5.2 使用场景
- 对于不能抛出的异常类型,可以将其包装成能抛出的类型,再抛
- 异常简化——把多种类型异常,简化成一种
5.3 方法重写 Override
- 重写方法时,异常管道,不能比父类方法多
5.4 练习:异常包装
package 异常;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Test1_异常包装 {
public static void main(String[] args) {
f();
}
private static void f() {
/*
* 对一组日期字符串排序 "2019-3-1" "2019-3-4" "2019-3-6" "2019-3-11" "2019-3-18" "2019-3-25"
*/
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "2019-3-1", "2019-3-4", "2019-3-6", "2019-3-11", "2019-3-18", "2019-3-25"); // 一次性添加多个元素
// for-each循环遍历,本质是迭代器
for (String s : list) {
System.out.println(s);
}
System.out.println("--------------------------------");
Collections.sort(list);// 按字符串的字符编码排序
for (String s : list) {
System.out.println(s);
}
System.out.println("--------------------------------");
Collections.sort(list, new Comparator<String>() {// 匿名类的比较器对象
@Override
public int compare(String o1, String o2) {
// 把日期字符串变成Date对象:2019-3-12 => Date对象
// SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
Date d1 = sdf.parse(o1);
Date d2 = sdf.parse(o2);
return d1.compareTo(d2);
} catch (ParseException e) {//此处无法添加异常管道throws,因为子类不能超出父类的管道范围
throw new IllegalArgumentException(e);// 非法参数异常,将ParseException包装成IllegalArgumentException抛出
}
}
});
for (String s : list) {
System.out.println(s);
}
System.out.println("--------------------------------");
}
}
六、自定义异常
6.1 概述
- 现有异常类型,不能表示业务中遇到的所有错误情况,这时就需要根据业务需要,自定义异常类型了,例如:
转账错误 ZhuanZhangShiBaiException
用户名 UsernameNotFoundException
密码错误 WrongPasswordException
- 自定义异常
起一个合适的类名
选一个合适的父类
添加合适的构造方法
6.2 练习:自定义异常
package 异常;
import java.util.Scanner;
public class Test2_自定义异常 {
public static void main(String[] args) {
f();
}
private static void f() {
System.out.println("用户名:");
String name = new Scanner(System.in).nextLine();
System.out.println("密码:");
String pass = new Scanner(System.in).nextLine();
try {
login(name,pass);
System.out.println("欢迎登陆!");
} catch (UsernameNotFoundException e) {
System.out.println("用户名错误!");
}catch (WrongPasswordException e) {
System.out.println("密码错误!");
}
}
private static void login(String name, String pass) throws WrongPasswordException, UsernameNotFoundException {
if(name.equals("admin")&&pass.equals("admin")) {
return;
}else if(name.equals("admin")) {
throw new WrongPasswordException();
}else if(pass.equals("admin")) {
throw new UsernameNotFoundException();
}
}
}
package 异常;
public class UsernameNotFoundException extends Exception{
// Exception没有默认管道,必须添加管道才能抛出
// 参考父类构造方法,添加子类的构造方法,alt + shift + s
public UsernameNotFoundException() {
super();
}
public UsernameNotFoundException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public UsernameNotFoundException(String message, Throwable cause) {
super(message, cause);
}
public UsernameNotFoundException(String message) {
super(message);
}
public UsernameNotFoundException(Throwable cause) {
super(cause);
}
}
package 异常;
public class WrongPasswordException extends Exception{
public WrongPasswordException() {
super();
}
public WrongPasswordException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public WrongPasswordException(String message, Throwable cause) {
super(message, cause);
}
public WrongPasswordException(String message) {
super(message);
}
public WrongPasswordException(Throwable cause) {
super(cause);
}
}