Exception异常
异常处理方式:抛出异常(throws)、捕获异常(try...catch)
// 抛出异常
方法 throws Exception {}
// 捕获异常
// 可以处理多个异常,子类异常在上面的catch,最后使用exception接收未知异常
try {
// 可能出现异常的代码
}catch (Exception e){
e.printStackTrace();
}
处理方案
- 使用throws/throw往上抛出异常。最后进行处理,给用户返回友好的反馈。
- 使用try~catch进行捕获,不抛出异常。catch进行处理,并恢复程序。
自定义异常
常见异常
编译时异常(Exception)
-
IOException: I/O 操作中发生的异常
-
SQLException:数据库操作相关的异常
-
ClassNotFoundException:程序试图加载一个不存在的类
运行时异常(RuntimeException)
- NullPointerException:尝试访问一个 null 引用的成员
- ArrayIndexOutOfBoundsException:尝试访问数组的非法索引
- ArithmeticExcepiton:算术运算中的异常
- IllegalArgumentException:传递给方法的参数不合法
- ClassCastException:非法类型转换
- NoSuchMethodException:尝试访问一个不存在的方法
- 使用反射(Reflection)API 时抛出
- 方法名拼写错误、参数类型不匹配或方法访问权限不足等情况
错误(Errors)
-
OutOfMemoryError:JVM内存不足
- 程序中存在内存泄露
- 分配了过大的数组或集合
-
StackOverflowError:栈溢出
- 无限递归
泛型
泛型(Generics)是编程语言中的一种特性,它允许开发者在定义类、接口或方法时使用类型参数(Type Parameters),从而实现代码的复用性和类型安全。泛型的核心思想是让代码能够处理多种数据类型,同时在编译时保证类型的安全性。
泛型不支持基本数据类型,只支持对象类型(引用数据类型)
泛型类
public class MyList<T> {
ArrayList<T> list = new ArrayList<>();
T getData(int index){
return list.get(index);
}
void addData(T data){
list.add(data);
}
}
泛型接口
public interface Data<T> {
void add(T t);
void update(T t);
T getDate(int id);
void delete(int id);
}
泛型方法
public class GenericityDemo1 {
public static void main(String[] args) {
int data1 = 100;
String str = "123123";
myPrint(data1);
myPrint(str);
}
// T可以接收任意类型,所以函数可以打印任何类型数据
public static <T> void myPrint(T t) {
System.out.println(t);
}
}
泛型的类型参数
-
类型参数的命名
- T(Type):表示任意类型
- E(Element):表示集合中的某个元素
- K(Key):表示键的类型
- V(Value):表示值的类型
- N(Number):表示数字的类型
-
类型参数的限制
public class Box<T extends Number> { // 上界限制 // T 必须是 Number 或其子类 private T content; ... } public static <T super Integer> void printList(List<T> list) { // 下界限制 // T 必须是 Integer 的父类 ... }
通配符(Wildcards)
-
无界通配符:? 表示任意类型
例如:List<?> 表示一个未知类型的列表
-
有界通配符:
-
上界通配符:? extends T 表示类型参数是 T 或其子类。
例如:List<? extends Number> 表示一个存储 Number 或其子类的列表
-
下界通配符:? super T 表示类型参数是 T 或其父类。
例如:List<? super Integer> 表示一个存储 Integer 或其父类的列表
-
包装类
| 基本数据类型 | 对应的包装类(引用数据类型) |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| char | Character |
| float | Float |
| double | Double |
boolean | Boolean |
基本数据类型变成包装类对象
Integer data1 = Integer.valueOf(24); // -128~127之间的Integer对象是相同的,因为Integer类中维护了一个数组,只有超出各个范围才会创建一个新的对象。
Integer data2 = 24; // java支持自动装箱
int data = data2; // 自动拆箱
// 面试题
Integer data3 = 24;
Integer data4 = 24;
System.out.println(data1 == data2) // true
Integer data5 = 454;
Integer data6 = 454;
System.out.println(data1 == data2) // false 创建对象之后,`==`比较的就是两个引用类型的地址
包装类的其他功能
// 1. 可以把基本数据类型转换成字符串类型
// 2. 可以把字符串类型的数值转换成数字本身对应的真实数据
Integer i = 100;
String str = i.toString();
System.out.println(str);
Integer i2 = Integer.parseInt(str);
System.out.println(i2);
为什么要有包装类
为了万物皆可对象,并且泛型和集合都不支持基本数据类型,支持包装类。
集合体系结构
Collection容器
常用方法
遍历方法
Collection<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
// 普通for循环遍历,有索引的容器才能如此遍历
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
// 方式一:迭代器遍历
Iterator<String> it = list.iterator();
while (it.hasNext()){
String s = it.next(); // next()方法返回迭代器指向的元素,并迭代到下一个位置
System.out.println(s);
}
// 方式二:增强for循环遍历
for (String s : list) {
System.out.println(s);
}
// 方式三:Lambda表达式遍历
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
// 函数式接口,所以可以简化
list.forEach( (s) -> {System.out.println(s);} );
list.forEach( s -> System.out.println(s); );
// 前后参数形式一致,可以使用方法引用(一般不使用)
list.forEach( System.out::println );
List容器
-
ArrayList底层是基于数组存储数据的- 查询速度快(根据索引查询快)
- 增删数据效率较低
底层源码: 第一次扩容为10,二次扩容为原来的1.5倍。
-
LinkedList底层是基于双向链表存储数据的**(queue、stack)**- 查询速度慢(无论查询哪个数据,都要从头开始找)
- 链表增删相对快(首尾最快)
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
// 通过index插入数据
list.add(2, "赵四");
// 通过index删除数据
list.remove(2);
// 通过index修改数据
list.set(2, "赵四");
// 获取数据
list.get(2);
// LinkedList也拥有以上函数方法,新增了许多针对于首尾元素的操作方法
LinkedList<String> list = new LinkedList<>();
// 列举 LinkedList 特有的函数
list.addFirst("a");
list.addLast("b");
System.out.println(list.getFirst());
System.out.println(list.getLast());
list.removeFirst();
list.removeLast();