异常的分类
异常在java里是一种类,所有异常类的根类都是Throwable
异常都是继承至Throwable,异常分为两个大类:
一是Error,一般是虚拟机异常,这种错误我们的代码没有办法处理
二是Exception异常,我们的代码可以抛出异常或者处理异常
简单来说就是将区域的代码报错合并起来提示,并且可以不终止程序,而是在发出异常后,跳过这段代码继续执行程序
Exception又分为两大类别:
- RuntimeException 运行时异常
- 非运行时异常
- Error
Error的异常一般不需要我们代码抛出
如果抛出了Error错误,不需要添加try catch 或 方法上加 throws
异常的产生
就是在我们的方法中遇到错误,或者无法处理,就会抛出异常,将异常部分的信息发送出来,并且跳过这部分
- 在代码中用throw 抛出一个Exception类型或子类型的对象
- 在方法上面添加一个throws声明,后面的异常类型要大于等于代码中抛出的异常
//在方法上面需要添加 thorws声明,后面的异常类型要大于等于代码中throw的类型
public String getSex(int sex) throws Exception {
if (sex == 0){
return "女";
}else if (sex == 1){
return "男";
}else{
//抛出异常,用throw关键字,后面跟Exception类型(或子类)的对象
//参数的字符串就是异常的消息
throw new Exception("性别只能是1或0");
}
}
处理异常
当我们调用的方法抛出了非Runtime的异常,就会报编译错误,
要求代码添加try catch语句来处理异常,catch语句可以有多个,也可以只有一个(如果只有一个catch,这个异常类型要大于等于抛出的最大的那个异常类型)
finally语句块的代码一定会被执行的(不管有没有异常都会执行)
只要有非运行时异常时try catch语句必不可少,但是finally是可选的
try {
createException.getName();
createException.getSex(2);
System.out.println("出现异常语句之后的代码");
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally {
//finally的代码一定会被执行
System.out.println("finally语句块");
}
System.out.println("try语句之后的代码");
运行时的异常
如果方法中抛出的继承RuntimeException的类型异常,不会强制要求添加throws 或try catch,不会导致编译错误,只有运行时有可能抛出异常
try {
createException.division(3, 0);
}catch (RuntimeException e){
e.printStackTrace();
}
public int division(int a, int b){
if (b == 0){
throw new RuntimeException("除数不能为零");
}
return a/b;
}
自定义异常的类
自定义异常类需继承Exception或RuntimeException
添加构造方法
package com.hqyj;
public class ProductException extends Exception{
public ProductException() {
}
public ProductException(String message) {
super(message);
}
}
使用自定义的异常类
try {
throw new ProductException("产品异常");
} catch (ProductException e) {
e.printStackTrace();
集合
一些数据结构,包含List,Set,Map
List
List就是列表,用来存储一组数据的数据结构
List可变长的数据结构,可以知道List里面存有多少个数据
List里面可以保存不同类型的数据
List是有序列表,数据可以重复
ArrayList
ArrayList是采用数组方式实现的
读写和遍历比较快,插入和删除数据比较慢
-
List的基本使用
add()
get()
size()
package com.hqyj;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
//用ArrayList创建一个List类型的对象
List list = new ArrayList(); //默认长度为10,自动扩展
//add()向列表添加元素
list.add(5);
list.add("abc");
list.add(null);
list.add(5);
//size()返回列表的实际数据的个数
System.out.println(list.size());
//get()返回指定下标的元素,下标从0开始
Integer o = (Integer) list.get(0);
System.out.println(o);
String o1 = (String) list.get(1);
System.out.println(o1);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
- List的扩展方法
//在指定下标位置插入一个数据,原来位置的数据往后面移动一位
list.add(2,3.14);
//替换指定下标位置的元素
list.set(0,"abcd");
//是否包含某个元素,结果是true/false
System.out.println(list.contains("abc"));
//删除对应下标的元素
list.remove(3);
//返回指定元素在列表中的位置,没找到返回-1
System.out.println(list.indexOf("abc"));
//截取子列表,左闭右开
List listsub = list.subList(1,3);
//列表转换成数组
Object[] array = list.toArray();
System.out.println("数组长度:"+ array.length);
//通过Arrays工具类把数组转列表
List objectList = Arrays.asList(array);
//清除所有数据
list.clear();
//是否为空
System.out.println(list.isEmpty());
for (Object obj : list) {
System.out.println(obj);
}
}
LinkedList
采用双向链实现的,插入和删除速度快,查询和遍历速度慢
- 插入和删除速度快
- 查找和遍历速度慢
- 链表里面的数据是保存的地址
- 每个节点除了自身数据的地址歪,还保存下一个和下一个节点的地址
package com.hqyj;
import java.util.LinkedList;
import java.util.List;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add(5);
list.addFirst(1);
list.addLast(9);
System.out.println(list.getLast());
System.out.println(list.getFirst());
list.removeLast();
list.removeFirst();
list.add(4);
list.add(99);
list.add("asdsa");
//出栈,弹出第一个元素(会从列表中删除)
System.out.println("弹出元素:" + list.pop());
//入栈(压栈),在最前面插入一个元素
list.push(3);
System.out.println("====================");
for (Object obj : list) {
System.out.println(obj);
}
}
}
泛型
因为List可以存各种类型的数据,但是取出来的都是Object,所以需要进行强制类型转换
相当于直接给列表定了一个类型,所有的这里面的都是一个类型
泛型就是用来解决这个问题,在创建List对象时指定存储的类型,在add和get自动就采用泛型指定的类型
泛型不能是基本类型,只能是引用类型
泛型使用
//使用泛型,定义变量时,类型后面跟上尖括号,尖括号写上数据类型
// new对象时 类后面也要有尖括号,尖括号里不写类型,默认定义变量泛型一致
List<String> listStr = new LinkedList<>();
//一旦指定泛型后,相关方法的参数,返回类型都跟泛型的类型一样
listStr.add("维拉斯");
listStr.add("服务器");
String s = listStr.get(0);
System.out.println(s);
Set
无序集合,元素不重复
没有索引(序号),不能通过下标访问
哈希表(hash table)
哈希表,散列表,是一种高效的数据结构
要保存的数据称为值,根据hash算法给每一个值算出一个hash code
保存数据就用hash code 跟值一一对应
如下图所示,左边是数组的方式保存数据,右边是用哈希表方式保存
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cCJiKZAz-1660494916382)(C:\Users\19638\AppData\Roaming\Typora\typora-user-images\image-20220803173813169.png)]
hash table保存数据的原理
根据hash code从表里面去查找是否存在:
- 不存在,直接添加
- 存在,在判断equals是否相等;
- false 直接添加
- true 说明两个值是一样的,不添加
Hash code 的结论:
- 两个值的hash code相同,它们的equals不一定相同
- 两个值的equals相同,hash code 不一定相同
- 两个值hash code相同,equals也相同,那么这两个值一定是相同的