文章目录
- 1.错误和异常区别:Arrays.toString(array)
- 2.编译和运行异常:SimpleDateFormat
- 3.处理异常:方法声明抛出
- 4.finally关键字:catch相当于else if,finally相当于else,return
- 5.自定义异常:extends
- 6.练习:常见异常
1.错误和异常区别:Arrays.toString(array)
package com.itheima01.throwable;
import java.util.Arrays;
//错误(Error) : 从程序角度 只能避开,不能解决。 异常(Exception) : 从程序角度 可以解决的问题
public class ThrowableDemo {
public static void main(String[] args) {
// int[] array = new int[3];
//System.out.println(array); //[I@6d6f6e28
//System.out.println(array.toString()); //[I@6d6f6e28
//System.out.println(Arrays.toString(array)); //[0, 0, 0]
// int[] array = new int[2_000_000_000]; //20亿撑不住,内存条不够
// System.out.println(Arrays.toString(array)); //java.lang.OutOfMemoryError: Java heap(堆) space //OOM :内存溢出【错误】
int[] array = {};
System.out.println(array[1]); //java.lang.ArrayIndexOutOfBoundsException【异常】
}
}
package com.itheima02.jvm;
import java.util.ArrayList;
/*
* throw 关键字(全小写): 1. 效果等同于return,后续代码不再执行
* 2. throw + Throwable对象(只能跟异常对象); return 返回值;
* 3. 运用: 我们一般不使用, JDK方法的设计者 (抛出异常: api设计者 和 使用者交流方式)
*/
public class ThrowDemo {
public static void main(String[] args) {
// new ArrayList<String>(-1); //IllegalArgumentException
int[] array = {0,1};
int element = getElement(array);
System.out.println(element);
}
private static int getElement(int[] array) {
int index = 2;
if(index > array.length - 1){ //>2-1
//访问了数组不存在的索引
// ArrayIndexOutOfBoundsException e = new ArrayIndexOutOfBoundsException("you are a stupid bird,you access a wrong index:" + index);
// throw e; //抛出异常,下面代码不会执行。抛出去之后也没人处理
throw new ArrayIndexOutOfBoundsException(index); //这一行等同上两行
//throw new Throwable(""); //也可以,因为是编译异常,声明getElement方法后要加throws Throwable
}
int element = array[index]; //上面有throw,这里两行都不执行
return element;
}
}
2.编译和运行异常:SimpleDateFormat
public class ExceptionDemo {
public static void main(String[] args) throws IOException {
String str = "1996-01-01";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(sdf); //java.text.SimpleDateFormat@f67a0200
// sdf.parse(str); //解析异常ParseException也叫编译异常,和IOException并列关系,main声明需抛出。
Date parse = sdf.parse(str); //加上Date parse不报错
System.out.println(parse); //Mon Jan 01 00:00:00 CST 1996
// FileOutputStream fos = new FileOutputStream(""); //FileNotFoundException是IOException子类
// fos.write(97); //IOException是最经典的编译异常
//111111111111111111111111111111111111111111111以下都为RuntimeException的子类
// 1. NullPointerException 空指针
String s = null;
// System.out.println(s.length());
// 2. IndexOutOfBoundsException 索引越界
int[] array = {};
// System.out.println(array[1]);
// 3. ClassCastException 类转换
// 4. IllegalArgumentException 非法参数
new ArrayList<String>(-1);
}
}
3.处理异常:方法声明抛出
package com.itheima03.throwsd;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ThrowsDemo {
public static void main(String[] args) throws IOException {
method01(); //表哥又抛出去叫大哥(jvm,因为main方法调用者是jvm),jvm出错又打印终止
}
/*
* throws 关键字
* 1. 用在方法声明上: 修饰符 返回值类型 方法名(参数列表) throws 异常类型(A)
* 2. 这是处理异常的一种方式: 声明将异常抛出给调用者处理(假手与人)
* 3. 注意: 这里的异常类型A 必须跟方法里要抛出的异常B一致, 或者A是B的父类 (向上转型)
*
* 语法: throws 异常1,异常2{ }
* 运用: 我们可以在某一方法的设计上先声明抛出异常,可以方法的调用处进行处理
* 切记有有一环节必须处理, 不然到JVM中, 出现异常就崩溃
* 我们平时学习为了省事, 如果明知不会错的异常,直接throws
*/
private static void method01() throws IOException { //交给表哥
FileOutputStream fos = new FileOutputStream("a.txt");
fos.write(97);
}
}
package com.itheima04.trycatch;
public class TrycatchDemo {
public static void main(String[] args) {
int[] array = {0,1};
try{
int element = array[2];
System.out.println(element);
}catch (Exception e){
e.printStackTrace();//打印异常信息: 打印栈中追溯,案发地点在方法栈中。jvm不会打印了,我们自己手动打印。这行注释了,下面红字不会打印,但“出现异常..继续运行...”都会打印出。
System.out.println("出现异常,并被捕获了");
}
System.out.println("程序继续执行");
}
}
package com.itheima04.trycatch;
import java.util.Scanner;
/*
* try...catch运用: 1. 如果代码都是由我们自己编写的,我们一般都不会出现异常
* 2. 有些代码需要用户参与编写 (交互: 我们程序输出,用户输入)
*思想: 我们预知代码可能运行结果(如果了包含了异常, 提前try...cath并给出提示或者解决方案)
*/
public class TryCatchDemo02 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个被除数:");
int a = sc.nextInt();
System.out.println("请输入一个除数:");
int b = sc.nextInt();
try {
int result = a/b; //java.lang.ArithmeticException: / by zero 算术异常
System.out.println(result);
}catch (Exception e){
System.out.println("你个傻鸟,除数不能为0");
}
System.out.println("软件继续让你玩");
}
}
package com.itheima04.trycatch;
/*
try{
}catch (NullPointerException e){
//1. 如果出现了空指针,应该提示...
}catch (IndexOutOfBoundsException e2){
//2. 如果出现了索引越界, 应该提示...
}
思想: 异常的分类讨论
执行顺序:
如果try中代码发生异常, 那么多个catch会从上到下逐一尝试捕获,
如果被A捕获了,后续的catch不再执行
注意:
1. 前面catch中的异常类型不能是后面catch中的异常类型的父类或者相同 (因为这样的话,后续catch执行不到没有意义)
2. 后面catch中的异常类型可以是前面的父类
*/
public class TryCatchCatchDemo {
public static void main(String[] args) {
try{
method01(2);
}catch (NullPointerException e){
System.out.println("发生了空指针异常");
}catch (IndexOutOfBoundsException e2){
System.out.println("发生了索引越界异常");
}
System.out.println("代码继续执行");
}
//模拟: 这段代码可能有两个异常(一段代码里面不论可能有多少个异常,一次运行最多抛出一个异常)
private static void method01(int a) {
if(a == 1){
throw new NullPointerException("空指针"); //throw天生与其他代码互斥,一旦发生throw,其他代码不再运行
}else if(a == 2){
throw new IndexOutOfBoundsException("越界异常");
}else{
System.out.println("什么事都没发生");
}
}
}
4.finally关键字:catch相当于else if,finally相当于else,return
package com.itheima04.trycatch;
/*
try{
}catch (Exception e){
}finally {
// 无论如何,一定最后执行。作用: (IO流)释放资源
}
*/
public class FinallyDemo {
public static void main(String[] args) {
// method();
int number = method2(); //运行 :3
System.out.println(number); //1
}
//111111111111111111111111111111111111111111111111111111111111111111111
private static int method2() {
int i = 1;
try{
// System.exit(0); //拔电源阻止finally
return i;
//一般return后续代码不会执行了,但finally会抢夺try...catch中的return执行权
//finally会先执行,执行完又回到return
//return 安全机制: 把i的值给记录下来了1 ,所以return 1
}catch (Exception e){ //没有异常,i永远不会=2
i = 2;
}finally {
i = 3;
System.out.println("运行 :" + i);
}
return i; //不执行,因为try catch finally有return了
}
//11111111111111111111111111111111111111111111111111111111111111111111
private static void method() {
try{
int i = 4/0;
System.out.println(i);
}catch (NullPointerException e){
System.out.println("异常发生了");
}finally {
System.out.println("无论如何一定执行");
}
System.out.println("程序继续执行");
}
}
5.自定义异常:extends
package com.itheima05.custom;
/*
* JavaBean : 标准类 (封装)
* 1. private属性
* 2. public get set方法
* 3. public 空参构造,不声明构造会有一个空参构造。 写满参构造就得写空参构造。
*
* 封装: 1. private属性 为了不对外直接暴露 -> 安全
* 2. public get set方法【方法跟属性最大不同, 方法可以加条件判断(健壮性校验)】
*
* 继承: 自定义异常
*/
public class Student {
private String name;
private int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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 < 0){
// throw new IllegalArgumentException("你个傻鸟,age没有负数");
throw new NoAgeException("你个傻鸟,age没有负数"); //不报错,因为下面class NoAgeException extends 。。。
}
this.age = age;
}
}
package com.itheima05.custom;
/*
* 自定义异常: IllegalArgumentException : 非法参数异常
* NoAgeException : 非法年龄异常(框架: 很多JDK没有的异常,自定义)
*/
public class CustomDemo {
public static void main(String[] args) {
Student s = new Student();
s.setName("张三");
// s.age = -18; // 非法访问,安全隐患,所以private int age;
s.setAge(-18); //在方法里加安全机制
System.out.println(s);
}
}
class NoAgeException extends IllegalArgumentException{
public NoAgeException(String msg){
super(msg); //调用IllegalArgumentException,Ill..又调用自己的super。。
}
}
如下是方法重写注意事项。
package com.itheima06.notice;
import java.io.IOException;
/*
* 现象: 1. 父类 方法中声明编译异常【void method() throws IOException{}】,而子类没有声明编译异常 不会报错
* 2. 父类 方法中未声明编译异常,而子类有声明编译异常 会报错 !!!!!
*
* 解释: 现象2 跟 多态冲突了
* 1.现象2在多态中,编译器只看左边,父类方法没有编译异常,以为没有编译异常,不需要处理
* 2.运行看右边,子类重写的方法运行时有编译异常 (编译异常要求编译时期必须处理)
* 冲突: 编译异常 绕过了 编译器 (编译器强制报错)
*/
public class NoticeDemo {
public static void main(String[] args) throws IOException {
Fu fu = new Zi(); //编译看左边,运行看右边
fu.method();
}
}
class Fu{
void method() {
}
}
class Zi extends Fu{
@Override
void method() throws RuntimeException{//不报错 //throws IOException编译异常会报错,运行异常不报错。
}
}
6.练习:常见异常
package com.atguigu.test01.review;
// 编写代码演示栈内存溢出 *Error(递归导致内存溢出)
public class TestError1 {
public static void main(String[] args) {
Son s = new Son();
s.test(); //自己调用自己,不调用父类test()方法。java.lang.*Error
}
}
class Father{
public void test(){
System.out.println("父类的");
}
}
class Son extends Father{
public void test(){
//调用父类的test();要用super.test()
test();
System.out.println("子类的");
}
}
package com.atguigu.test01.review;
import java.util.ArrayList;
// 请编写代码演示OOM:OutOfMemoryError
public class TestError2 {
public static void main(String[] args) {
//1、答案一:创建一个超级大数组,
//数组的长度的类型是int,Integer是int类型的一个包装类,Integer.MAX_VALUE是2的31次方-1
// int[] arr = new int[Integer.MAX_VALUE];
//2、答案二:不断的创建对象
ArrayList list = new ArrayList();//容器,用来装对象
while(true){
list.add(new Object());
}
}
}
public class TestFinallyNoReturn2 {
public static void main(String[] args) {
int num = getNum(4);
System.out.println(num);//0,不是30
}
public static int getNum(int a){
int result = 10;
try{
System.out.println(a/0); //直接跳到catch
if(a > 0){
result = 20;
return result;
}else if(a < 0){
result = -20;
return result;
}else{
return result;
}
}catch(Exception e){
System.out.println("exception");
result = 0;
return result;
}finally{
result = 30;
System.out.println("finally");
// return result;//如果有这句,最后一行结果就变成30
}
}
}
如下重写和抛异常两个报错。
微信公众号:码农编程录