泛型、反射、编译优化
实现了Serializable接口缺报错怎么办?
序列化和反序列化
- 序列化:将对象写入到IO流中
- 反序列化:从IO流中恢复对象
Serializable接口:是一个标记接口,不用实现任何方法,标记当前类对象是可以序列化的
序列化需要考虑哪些问题?
- 子类实现序列化接口,父类没有实现,那么,子类可以序列化吗?
只要父类实现了无参构造函数,子类可以序列化
- 类中存在引用对象,那么,这个类对象在什么情况下可以实现序列化呢?
类中所有的对象都是可序列化的,才可以实现序列化
- 同一个对象多次序列化(之间有属性更新),会影响序列化吗?
会影响到序列化
泛型不仅仅是规定集合中的类型那么简单
泛型就是参数化类型,就是将类型由原来的具体的类型参数化
能够在不创建新类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型
类型擦除:编译期间,编译中不包含类型信息
private static void easyUse() throws Exception {
// List<String> left = new ArrayList<>();
// List<Integer> right = new ArrayList<>();
//
// System.out.println(left.getClass());
// System.out.println(left.getClass() == right.getClass());
// if(left instanceof ArrayList<String>){
//
// }
// 正确写法
// if(left instanceof ArrayList){
//
// }
// if(left instanceof ArrayList<?>){
//
// }
List<Integer> list = new ArrayList<>();
list.add(1);
list.getClass().getMethod("add",Object.class).invoke(list,"abcd");
list.getClass().getMethod("add",Object.class).invoke(list,"1.2");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
运行结果: 对于left.getClass()会返回ArrayList,对于两个类型是否相等,自然会返回true,因为都是ArrayList。利用反射在运行期间塞入不同类型的值,是可以通过成功输出的。原因就在泛型参数类型擦除。
![image-20230619000750627](https://img2023.cnblogs.com/blog/1483664/202306/1483664-20230619000756620-1163910501.png)
如下图,在编译前先检查已经出现报错了
![image-20230619001410099](https://img2023.cnblogs.com/blog/1483664/202306/1483664-20230619003215553-2092367699.png)
private static void genericityCanNotExtend(){
// 第一类错误 引用传递不支持继承
// ArrayList<String> first = new ArrayList<Object>();
//
// ArrayList<Object> list1 = new ArrayList<>();
// list1.add(new Object());
// ArrayList<String> list2 = list1;
// 第二类错误
ArrayList<Object> second = new ArrayList<String>();
ArrayList<String> list1 = new ArrayList<>();
list1.add(new String());
ArrayList<Object> list2 = list1;
}
![image-20230619002122502](https://img2023.cnblogs.com/blog/1483664/202306/1483664-20230619003213221-1849513422.png)
/**
* 泛型类型变量不能是基本数据类型: 类型擦除后是Object类型,不能存储int数据类型
*/
private static void baseTypeCanNotUseGenericity(){
List<int> invalid = new ArrayList<>();
}
/**
* 泛型的类型参数只能是类类型,不能是简单类型
*/
private static <T> void doSomeThing(T... values){
for(T value:values){
System.out.println(value);
}
}
举例:泛型类相参数 分别是 类类型和 简单类型
/**
* 泛型的类型参数只能是类类型,不能是简单类型
*/
private static <T> void doSomeThing(T... values){
for(T value:values){
System.out.println(value);
}
}
public static void main(String[] args) throws Exception {
Integer [] inst1 = new Integer[]{1,2,3};
int[] inst2 = new int[]{1,2,3};
doSomeThing(inst1);
System.out.println("---------------");
doSomeThing(inst2);
}
输出结果:类类型被正确打印,而简单类型将数组整体作为泛型类型值打印。
![image-20230619003020794](https://img2023.cnblogs.com/blog/1483664/202306/1483664-20230619003206035-1241794142.png)
切记不要使用原始类型,这可能会出现灾难性的后果
原始类型可用的场景和坑
![image-20230620233342869](https://img2023.cnblogs.com/blog/1483664/202306/1483664-20230620233347576-1895900725.png)
初步优化 : 使用List