异常
throw关键字
public class ExceptionClass {
public static void main(String[] args) {
int[] arr = null;
int element = getElement(arr, 4);
System.out.println(element);
}
public static int getElement(int[] arr, int index) {
if(arr == null) {
throw new NullPointerException("传递的数组是空数组");
}
if(index < 0 || index > arr.length - 1) {
throw new ArrayIndexOutOfBoundsException("超过最大索引值");
}
int ele = arr[index];
return ele;
}
}
异常处理
1.交给别人处理(抛出给JVM处理)
public class NewException {
public static void main(String[] args) throws IOException { /*FileNotFoundException为
IOException的子类,可省略该子类*/
method("d:\\a.tx");
}
public static void method(String name) throws IOException {
if(!name.equals("c:\\a.txt")) {
throw new FileNotFoundException("传递路径不是c:\\a.txt");
}
if(!name.endsWith(".txt")) { //上面抛出异常后会中止程序执行,要验证该代码需要将上面的代码注释掉
throw new IOException("文件后缀名不对");
}
}
}
2.自己处理(try…catch)
public class NewException {
public static void main(String[] args){
try{
method("d:\\a.tx"); //可能出现异常的代码
}catch (IOException e){
System.out.println("路径不对"); //自己处理
}
}
public static void method(String name) throws IOException {
if(!name.equals("c:\\a.txt")) {
throw new FileNotFoundException("传递路径不是c:\\a.txt");
}
}
}
throwable类中处理异常的三个方法
public class NewException {
public static void main(String[] args){
try{
method("d:\\a.tx"); //可能出现异常的代码
}catch (IOException e){
// System.out.println(e.getMessage()); //传递路径不是c:\a.txt
// System.out.println(e.toString()); //java.io.FileNotFoundException: 传递路径不是c:\a.txt
e.printStackTrace(); /*java.io.FileNotFoundException: 传递路径不是c:\a.txt
at com.learning.demo02.NewException.method(NewException.java:19)
at com.learning.demo02.NewException.main(NewException.java:9)*/
}
}
public static void method(String name) throws IOException {
if(!name.equals("c:\\a.txt")) {
throw new FileNotFoundException("传递路径不是c:\\a.txt");
}
}
}
Objects.requireNonNull
public class RequireClass {
public static void main(String[] args) {
int[] arr = null;
Objects.requireNonNull(arr,"你输入的对象为空");
}
}
这样就不需要自己写判断是否为空并抛出异常的代码了
finally代码块
public class NewException {
public static void main(String[] args){
try{
method("d:\\a.tx"); //可能出现异常的代码
}catch (IOException e){
e.printStackTrace();
}finally {
System.out.println("资源释放"); //仍然会执行
}
}
public static void method(String name) throws IOException {
if(!name.equals("c:\\a.txt")) {
throw new FileNotFoundException("传递路径不是c:\\a.txt");
}
}
}
ps:最好别在final中写入return语句,否则前面处理return错误的结果会被覆盖,从而永远只执行final语句中的return语句。
public class OneToOne {
public static void main(String[] args){
int i = numMethod();
System.out.println(i);
}
public static int numMethod() {
int a = 10;
try{
return a;
}catch (Exception e) {
System.out.println(e);
}finally {
return 100; //永远返回的都是100
}
}
}
多异常的捕获处理
1.多个异常分别处理
public class OneToOne {
public static void main(String[] args){
try{
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}
try{
int[] arr = null;
System.out.println(arr[4]);
}catch (IndexOutOfBoundsException e) {
System.out.println(e);
}
}
}
2.多个异常一次捕获,多次处理
public class OneToOne {
public static void main(String[] args){
try{
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
List<Integer> list = List.of(1, 2, 3);
System.out.println(list.get(3));
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}catch (IndexOutOfBoundsException e) {
System.out.println(e);
}
System.out.println("后续代码");
}
}
另外,当catch的Exception分类存在子父类关系,需要把子类写在前面,如果不这样做,那么由于多态的关系,放在父类处理方式后面的子类将被父类阻挡,成为无用代码块。
3.多个异常一次捕获一次处理
public class OneToOne {
public static void main(String[] args){
try{
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
List<Integer> list = List.of(1, 2, 3);
System.out.println(list.get(3));
}catch (IndexOutOfBoundsException e) {
System.out.println(e);
}
System.out.println("后续代码");
}
}
ps:
2和3中的List.of是在JDK9后才有的,之前的版本不能用,功能为一次性为List添加多个元素,类似的还可以为Map集合以及Set集合。
子父类异常
public class ExceptionClass {
public void show01() throws NullPointerException,ClassCastException{}
public void show02() throws IndexOutOfBoundsException{}
public void show03() throws IndexOutOfBoundsException{}
public void show04() {}
}
class theSon extends ExceptionClass{
@Override
public void show01() throws NullPointerException, ClassCastException {}
//抛出异常子类或者不抛出
public void show02() throws ArrayIndexOutOfBoundsException{}
public void show03() {}
// public void show04() {} //不可抛出,如有异常只能捕获处理(try...catch)
public void show04() {
try{
throw new Exception("编译期异常");
}catch (Exception e) {
e.printStackTrace();
}
}
}
自定义异常类
public class RegisterException extends Exception{
public RegisterException() {
super();
}
public RegisterException(String message) {
super(message);
}
}
练习
public class ConcretClass {
static String[] usersNames = {"小新", "风间", "妮妮"};
public static void main(String[] args) /*throws RegisterException*/ {
Scanner scn = new Scanner(System.in);
System.out.println("请输入用户名:");
String usersName = scn.next();
checkName(usersName);
}
public static void checkName(String usersName) /*throws RegisterException*/ {
for (String name : usersNames) {
if(name.equals(usersName)) {
try {
throw new RegisterException("抱歉,用户名已经被注册");
} catch (RegisterException e) {
e.printStackTrace();
return;
}
}
}
System.out.println("恭喜,用户名未被占用");
}
}
ps:如果异常类父类为RuntimeException,即为运行期异常,throw不报错,运行期异常可以交由JVM处理(中断处理)