先复习集合:
ArrayList的底层:ArrayList的底层数据结构是数组,初始长度为0,在调用add方法时,把elementData数组长度初始到10,当数组长度填满之后进行数组扩容,增加新数组,新数组的长度是原数组长度的1.5倍
原数组的长度: int oldCapacity = elementData.length;
新数组的长度 int newCapacity = oldCapacity + (oldCapacity >> 1);(>>1是在二进制当中向右移了一位也就是旧长度+旧长度/2).
HashMap底层:底层数据结构是数组,链表,黑红树,初始长度为0,在调用put方法,把数组Node[]长度初始到16,当数组长度达到阈值(也就是数组长度*0.75)时,数组长度实现扩容,新数组长度为原来数组的2倍;Node中有key,value,hash,next在数组里边的位置是key的hash值%数组长度,当取余之后位置相同,进行链表存储(像极了压子弹),当链表长度达到8层时,就存储进二叉树。
HashSet 底层:底层数据结构是HashMap,调用add方法时底层调用HashMap的put方法,
去重:HashSet的值时HashMap的Key值,而Value只是Object属性的常量,Key是不可重复的,HashSet就不是重复的。
异常
概念:程序运行过程中出现的特殊情况。
异常的分类:
Throwable:可抛出的,一切异常的父类,位于Java.lang包下;
Error:JVM,硬件,执行逻辑错误,不能手动处理。
Exception:程序再运行与配置中产生的问题,可处理。
RuntimeException:运行时的异常,可处理,可不处理
。。。。。。。。
运行时异常
常见运行时异常的演示:
//1.java.lang.StackOverflowError 栈溢出异常 public static void m1(){ m1(); } //2.java.lang.NullPointerException 空指针异常 public static void m2(){ Object o = null; o.hashCode(); } //3.java.lang.ArithmeticException 算术异常 public static void m3(){ System.out.println(3/0); } //4.java.lang.ArrayIndexOutOfBoundsException 角标越界异常 分Array和String异常 public static void m4(){ int[] nums = new int[4]; System.out.println(nums[4]); } //5.java.lang.ClassCastException 类型转换异常 public static void m5(){ Object o = new Integer(15); Scanner s = (Scanner)o; } //6.java.lang.NumberFormatException 数字转换异常 public static void m6(){ new Integer("12a"); }
受检异常
ClassNotFoundException 类未找到异常
IOException IO异常
等等.....
受检异常必须处理,否则编译不通过。
异常的处理
try catch
//方式一:抛 向外声明这个异常,交给调用者去处理 //示例 : // 格式:throws 异常类型 public static void divid(int a,int b) throws ArithmeticException{ System.out.println(a/b); } 此时,意味着该方法是一个有异常的方法。 //方式二:try catch finally{} 格式: try{ 有可能出现异常的代码 }catch(可捕获的异常类型 e){ 处理 默认e.printStackTrace(); }finally{ //无论如何都会执行的代码块。 } 注意: catch 可以多个,但可捕获的异常类型一定是从小到大
自动抛
throws 异常类型 //可以有多个,中间用逗号隔开 抛给了调用者
手动抛
throw new 异常类型("异常信息");
异常传递
随着方法在栈当中的调用,异常也随着传递。
代码示例: try { artith(4,0); } catch (Exception e) { //可以捕获的 要大于 能捕获的 // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("后面的代码"); } public static void artith(int a,int b) throws ArithmeticException{ divid(a,b); } public static void divid(int a,int b) throws ArithmeticException{ System.out.println(a/b); } //控制台的异常信息如下: java.lang.ArithmeticException: / by zero at com.qf.exception.Demo3.divid(Demo3.java:22) at com.qf.exception.Demo3.artith(Demo3.java:18) at com.qf.exception.Demo3.main(Demo3.java:9)
自定义异常
步骤
1. 创建一个类,继承Exceptio类
2. 声明有参构造方法,并调用父类的有参构造,把异常信息作为参数传递。
步骤实例
public class Test { public static void main(String[] args){ try { login(); } catch (Exception e) { System.out.println(e.getMessage()); } } public static void login() throws LoginException, CheckCodeException{ Scanner sc = new Scanner(System.in); System.out.println("请输入用户名:"); String userName = sc.next(); System.out.println("请输入用密码:"); String pwd = sc.next(); if("张三".equals(userName) && "1234".equals(pwd)){ //当用户名和密码都对的情况下: System.out.println("请输入验证码:"); String check = sc.next(); if("abcd".equals(check)){ System.out.println("登录成功!"); }else{ //验证码不对时 throw new CheckCodeException("验证码不对"); } }else{ throw new LoginException("用户名或者密码不对!"); } } } //自定义异常 登录异常 //1. 继承 Exception 异常类 class LoginException extends Exception{ //2. 创建 无参和有参,构造方法 public LoginException(){ } public LoginException(String message){ super(message); } } //验证码异常 class CheckCodeException extends Exception{ public CheckCodeException(){ } public CheckCodeException(String message){ super(message); } }