【异常、断言】

发布于:2023-01-22 ⋅ 阅读:(12) ⋅ 点赞:(0) ⋅ 评论:(0)
所谓异常指的就是程序在 运行时 出现错误时通知调用者的一种机制 .

1、处理错误

如果由于出现错误而使得某些操作没有完成, 程序应该:

  • 返回到一种安全状态,并能够让用户执行一些其他的命令;或者
  • 允许用户保存所有操作的结果,并以妥善的方式终止程序。

1.1、异常分类

  • 其中 Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现。
  • Exception 是我们程序猿所使用的异常类的父类。
如果一段代码可能抛出 非检查型异常(非运行时异常) , 那么必须显式进行处理。

 

1.2、声明检查型异常

class MyAnimation{
    ...
    public Image loadImage(String) throws FileNotFoundException,EOFExcption{
    ...
    }
}

 需要记住在遇到下面 4 种 情况时应该抛出异常:

  • 调用一个抛出受査异常的方法, 例如, FilelnputStream 构造器。
  • 程序运行过程中发现错误, 并且利用 throw语句抛出一个受查异常。
  • 程序出现错误, 例如,a[-1] =0 会抛出一个 ArraylndexOutOfBoundsException 这样的非检查型异常。
  •  Java 虚拟机和运行时库出现的内部错误。

如果出现前两种情况之一, 则必须告诉调用这个方法的程序员有可能抛出异常。

1.3、如何抛出异常

对于一个已经存在的异常类并且能够满足自己的需求, 将其抛出非常容易。

在这种情况下:

  1. 找到一个合适的异常类。
  2. 创建这个类的一个对象。
  3. 将对象抛出。

 一旦方法抛出了异常, 这个方法就不可能返回到调用者。也就是说, 不必为返回的默认值或错误代码担忧。


String readData(Scanner in) throws EOFException{
		while() {
			if(!in.hasNext) {
				if(n<len) {
					throw new EOFException();
				}
			}
		}
        return s;
	}

1.4、创建异常类

        我们需要做的只是定义一个派生于 Exception 的类,或者派生于 Exception 子类的类。定义的类应该包含两个构造器, 一个是默认的构造器;另一个是带有详细描述信息 的构造器(超类 Throwable 的 toString 方法将会打印出这些详细信息, 这在调试中非常有用)。

class UserError extends Exception { 
     public UserError(String message) { 
     super(message); 
     } 
} 

class PasswordError extends Exception { 
     public PasswordError(String message) { 
     super(message); 
     } 
}

public static void main(String[] args) { 
     try { 
         login("admin", "123456"); 
     } catch (UserError userError) { 
         userError.printStackTrace(); 
     } catch (PasswordError passwordError) { 
         passwordError.printStackTrace(); 
     } 
} 
public static void login(String userName, String password) throws UserError,PasswordError { 
     if (!Test.userName.equals(userName)) { 
         throw new UserError("用户名错误"); 
        } 
     if (!Test.password.equals(password)) { 
         throw new PasswordError("密码错误"); 
     } 
     System.out.println("登陆成功"); 
}

2、异常的基本用法

2.1、捕获异常

基本语法:

try{ 
 有可能出现异常的语句 ; 
}[catch (异常类型 异常对象) {
} ... ]
[finally {
 异常的出口
}]
  • 程序先执行 try 中的代码
  • 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
  • 如果找到匹配的异常类型, 就会执行 catch 中的代码
  • 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
  • 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
  • 如果上层调用者也没有处理的了异常, 就继续向上传递。
  • 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.
public static void main(String[] args) {
    try {
        func();
   } catch (ArrayIndexOutOfBoundsException e) {
        e.printStackTrace();
   }
    System.out.println("after try catch");
}
public static void func() {
    int[] arr = {1, 2, 3};
    System.out.println(arr[100]);
}
// 直接结果
java.lang.ArrayIndexOutOfBoundsException: 100
 at demo02.Test.func(Test.java:18)
 at demo02.Test.main(Test.java:9)
after try catch
public static void main(String[] args) {
    func();
  System.out.println("after try catch");
}
public static void func() {
    int[] arr = {1, 2, 3};
    System.out.println(arr[100]);
}
// 执行结果
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
 at demo02.Test.func(Test.java:14)
 at demo02.Test.main(Test.java:8)

2.2、finally子句

  • finally 代码块中的代码用于处理善后工作, 会在最后执行。
  • 其中 catch fifinally 都可以根据情况选择加或者不加。
public static void main(String[] args) { 
 System.out.println(func()); 
} 
public static int func() { 
 try { 
 return 10; 
 } finally { 
 return 20; 
 } 
} 
// 执行结果
20
  • finally 执行的时机是在方法返回之前(try 或者 catch 中如果有 return 会在这个 return 之前执行 finally)。
  • 但是如果finally 中也存在 return 语句, 那么就会执行 fifinally 中的 return, 从而不会执行到 try 中原有的 return。
  • 一般我们不建议在 fifinally 中写 return (被编译器当做一个警告)。

2.3、try-with-Resources语句

带资源的 try 语句(try-with-resources) 的最简形式为:

try (Resource res = . . .)
{
work with res
}

 同时指定多个资源:

public class TryWithResource {
  public static void main(String[] args) {
    try (BufferedInputStream buIn = new BufferedInputStream(new FileInputStream(new File("1.txt")));
       BufferedOutputStream buOut = new BufferedOutputStream(new FileOutputStream(new File("2.txt")))) {
      int b;
      while ((b = buIn.read()) != -1) {
        buOut.write(b);
      }
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
}

        try-with-resources是jdk1.7引入的语法糖,使得关闭资源操作无需层层嵌套在finally。编译器也会自动帮我们补全close(),而且可以避免异常屏蔽。

3、异常的使用技巧

  1. 异常处理不能代替简单的测试
  2. 不要过分地细化异常
  3. 利用异常层次结构
  4. 不要压制异常
  5. 在检测错误时,“ 苛刻 ” 要比放任更好
  6. 不要羞于传递异常

4、使用断言

        设确信某个属性符合要求, 并且代码的执行依赖于这个属性。断言机制允许在测试期间向代码中插入一些检査语句。当代码发布时,这些插人的检测 语句将会被自动地移走。

   Java 语言引人了关键字 assert。这个关键字有两种形式:

  1. assert 条件;
  2. assert 条件:表达式;

        这两种形式都会对条件进行检测, 如果结果为 false, 则抛出一个 AssertionError 异常。 在第二种形式中,表达式将被传人 AssertionError 的构造器, 并转换成一个消息字符串。“ 表达式” 部分的唯一目的是产生一个消息字符串。

结语

        笔记自用。


网站公告

欢迎关注微信公众号

今日签到

点亮在社区的每一天
签到