JAVA入门笔记~基础知识day12

异常的概述和体系

1. 什么是异常?

  1. 异常是程序在编译或者执行的过程中可能出现的问题

  2. 异常是应该尽量提前避免的

  3. 异常可能也是无法做到绝对避免的,异常可能有太多情况了,开发中只能提前干预

  4. 异常一旦出现了,程序就会推出JVM虚拟机而终止,开发中异常是需要提前处理的

  5. 研究异常并且避免异常,然后提前处理异常,体系的是程序的健壮性!!!

  6. Java会为常见的代码异常都设计一个类来代表

2. 异常的体系

  1. Java中异常继承的根类是: Throwable(根类不是异常类)
  2. Error
    1. 错误的意思,严重错误Error,无法通过处理的错误,一旦出现,程序员无能为力,只能重启系统,优化项目(比如内存奔溃,JVM本身奔溃等,这个程序员无须理会)
  3. Exception
    1. 异常类,他是开发中代码在编译或者执行过程中可能出现的错误,他是需要提前处理的.一边程序更健壮!

3. Exception异常的分类

  1. 编译时异常
    1. 继承自Exception的异常或者其子类,编译阶段就会报错,必须程序员处理,否则代码编译就报错!
  2. RuntimeException(运行时异常)
    1. 继承自RuntimeExce的异常或者其子类,编译阶段是不会出错的,他是在运行时阶段可能出现,运行时异常可以处理也可以不处理,编译阶段是不会出错的,但是还是建议处理!

4. 小结

  1. 异常类: Exception
  2. 异常需要处理的,否则异常出现后,程序会死亡
  3. 异常分为两类: 编译时异常,运行时异常
  4. 编译时异常编译阶段就直接报错,程序员必须处理
  5. 运行时异常编译阶段不报错,运行阶段才报错!

常见的运行时异常

1. 数组索引越界异常

ArrayIndexOutOfBoundsException

 int[] arr1 = {10, 20 , 30};
 System.out.println(arr1[0]);
 System.out.println(arr1[1]);
 System.out.println(arr1[2]);
 System.out.println(arr1[3]); // 出异常了!

2. 空指针异常

NullPointerException

// 直接输出没有问题.但是调用空指针的变量的功能就会报错!String name = null

System.out.println(name); // 空指针直接输出没有问题,直接输出没有地址的类型:null

System.out.println(name.length());// 出异常了!

3. 类型转换异常

ClassCaseException

Object obj = "你好";
Integer it = (Integer) obj;  //报错了

4. 迭代器遍历没有此元素异常

NoSuchElementException

 List lists = new ArrayList<>();
 Collections.addAll(lists,"java1" ,"java2" ,"java2");
 Iterator it = lists.iterator();
 System.out.println(it.next());
 System.out.println(it.next());
 System.out.println(it.next());
 System.out.println(it.next()); // 出异常了!

5. 数字操作异常

ArithmeticException

int c = 10 / 0 ;  // 出异常了!
System.out.println(c);

6. 数字转换异常

NumberFormatException

String num = "12dsd";
int n = Integer.valueOf(num); // // 出异常了!
System.out.println(n);

7. 小结

  1. 运行时异常都是继承自RuntimeException,编译阶段不会报错,运行时才会出现
  2. 异常一旦出现了,假如没有处理,程序会立即在出现异常的地方死亡
  3. 运行时异常一般都是程序员技术太长(或者思考的不缜密)引起的

编译时异常认识

  1. 继承自Exception的异常或者其子类,没有继承RuntimeException
  2. 编译阶段就会报错,必须程序员处理的.否则代码编译就报错!
  3. 是在编译阶段就直接报错的,目的是担心写代码的程序员技术不行,提示你在这里可能很容易出现错误,需要注意!
  4. 运行时异常一般是程序员自己写代码引起的
  5. 编译时异常是体现程序员这里的代码要注意,可能出错,提醒的更强烈!
  6. 编译时异常是编译阶段就直接报错,一定要程序员在编译阶段处理的

异常的产生处理的默认过程

1. 过程解析

  1. 默认会在出现异常的代码那里自动的创建一个异常对象: RuntimeException
  2. 异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机
  3. 虚拟机接收的异常对象后,先在控制台直接输出异常栈信息数据
  4. 直接干掉当前程序
  5. 后续代码没有机会执行了,因为程序以及死亡

2. 小结

  1. 异常默认的处理机制是自动创建异常对象,抛出给调用者,调用者抛给虚拟机
  2. 虚拟机先打印出异常信息,然后直接干掉程序
  3. 默认的处理机制会引起程序的死亡,不够健壮,所有程序员要自己提前处理异常

编译时异常的处理机制

1. 格式

​ 抛出
​ throws 异常
​ 捕获
​ try{}catch(Exception e){}

2. 方式

  1. 方式一
    • 在出现异常的地方,一层一层的抛出给调用者,调用者抛出给JVM虚拟机
  2. 方式二
    • 自己捕获处理
    • 优点: 及时程序真的出现了异常,自己捕获处理了,不会引起程序的死亡
  3. 方式三
    • 在出现异常的地方把异常一层异常的抛出给最外层调用者,最外层调用者捕获处理!(规范做法)
  4. 小结
    • 最规范的方式,推荐使用
    • 外层可以知道底层执行的情况
    • 即使出现了错误也不会引起程序员的死亡,这是最好的方案

运行时异常的处理机制

  1. 运行时异常在编译阶段是不会报错,在运行阶段才会出错
  2. 运行时异常在编译阶段不处理也不会报错,但是运行时如果出错了程序还是会死亡
  3. 所以运行时异常也要处理
  4. 运行时异常是自动往外抛出的,不需要我们手工抛出
  5. 直接在最外层捕获处理即可,底层会自动抛出

finally关键字

1. 格式

try{
    代码块
}catch(异常类型 e){
    处理
}finally{
    代码块
}

2. 用途

  1. finally无论程序正常执行还是异常执行,都要执行一次
  2. 一般是用来在程序执行结束后,进行资源的回收操作

异常的注意事项

  1. 运行时异常被抛出可以不处理,可以自动抛出,编译时异常必须处理,按照规范都应该处理
  2. 如果父类抛出了多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是他的子集
  3. 父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常.此时子类产出该异常,只能捕获处理,不能声明抛出
  4. 当多异常处理时,捕获处理,前边的类不能是后边类的父类
  5. try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收

自定义异常

1. 自定义编译时异常

  1. 定义一个异常类继承Exception
  2. 重写构造器
  3. 在出现异常的地方用throw new自定义对象抛出
  4. 提醒更加强烈,一定需要处理!!

2. 自定义运行时异常

  1. 定义一个异常类继承RuntimeException
  2. 提醒不强烈,编译阶段不报错!!
  3. 重写构造器
  4. 在出现异常的地方用throw new 自定义对象抛出

多线程

1. 什么是进程?

  1. 程序是静止的,运行中的程序就是进程进程的
  2. 三个特征
    1. 动态性
      1. 进程是运行中的程序,要冬天的占用内存,CPU和网络等资源
    2. 独立性
      1. 进程与进程之间的相互独立的,彼此有自己的独立内存空间
    3. 并发性
      1. 加入CPU是单核,同一个时刻其实内存中只有一个进程在被执行.
      2. CPU会分时轮询切换依次为每个进程服务,因为切换的速度非常快,给我们的感觉这些进程在同时执行,这就是并发性.
  3. 并行
    1. 同一个时刻在同时执行

2. 什么是线程?

  1. 线程是属于进程的.一个进程可以包含多个线程,这就是多线程
  2. 线程创建开销相对于进程来说比较小
  3. 线程也支持并发性

3. 线程的作用:

  1. 可以提高程序的效率,可以有更多机会得到CPU
  2. 多线程可以解决很多业务模型
  3. 大型高并发技术的核心技术,设计到多线程的开发可能都比较难理解

4. 小结:

  1. 进程是运行中的程序.有动态性,独立性,并发性
  2. 一个进程可以包含多个线程,线程也支持并发
  3. 多线程可以提供程序的整体效率,线程也支持并发
  4. 多线程可以提高程序的整体效率,可以解决很多业务需求
  5. 因为多个线程是并发抢占CPU执行,所以多线程的执行会出现随机性

创建多线程的方式

1. 方式一

  1. 步骤
    1. 定义一个线程类继承Thread类
    2. 重新Thread类的run()方法
    3. 创建一个子线程对象
    4. 调用线程对象的start()方法启动线程(其实最终就是执行线程对象的run()方法)
  2. 线程的注意
  3. 启动线程不能直接调用run()方法,否则就是普通对象的普通方法调用,失去线程特征
  4. 线程的启动必须调用start()
  5. 一般是先创建子线程,再申明主线程的任务,否则主线程任务总是先执行完
  6. 优缺点
  7. 优点: 代码简单
  8. 缺点
    1. 已经继承了Thread类,不能再继承其他类,功能被削弱
    2. 不能做线程池
    3. 无法直接返回线程执行的结果
  1. 方式二
  2. 步骤
    1. 定义一个线程任务类实现Runnable接口.重新run()方法
    2. 创建一个线程任务对象
    3. 把线程任务对象包装成一个线程对象
      public Thread(Runnable target)
    4. 调用线程对象的start()方法启动线程
  3. 优缺点
    1. 缺点: 编程相对复杂,不能直接返回线程对象
    2. 优点
      1. 一个任务对象可以被反复包装成多个线程对象
      2. 可以避免java中的单继承的局限性.因为线程任务对象只是实现了接口,还可以继续继承其他类和实现其他接口
      3. 实现解耦操作,线程任务对象代码可以被多个线程共享,代码和线程独立
      4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类
      5. 适合做线程池

3. 方式三

  1. 步骤
    1. 定义一个线程任务类实现Callable接口
    2. 重新Call()方法
    3. 把线程对象任务包装成一个未来任务对象
    4. 把未来任务对象包装成一个线程对象
    5. 调用线程对象的start()方法启动线程
  2. 优缺点
    1. 缺点: 编码复杂
    2. 优点
      1. 可以继续继承其他类
      2. 可以做线程池
      3. 可以得到线程返回结果
      4. 可以做资源共享操作

线程的常用API

  • 线程是有默认名字的: 子线程的名称规则Thread_索引,main线程的默认名称就是main

  • API

    1. public void setName(String name)   // 给线程对象取名字
    2. public String getName()    // 返回线程对象的名字
    3. public static Thread currentThread()   // 获取当前线程对象,这个代码是哪个线程在执行就返回哪个线程对象
    

你可能感兴趣的:(JAVA入门笔记~基础知识day12)