Serializable接口
- 序列化:将对象写入到IO流中
- 反序列化:从IO流中恢复对象
- Serializable接口:是一个标记接口,不用实现方法(接口中没有定义方法),标记当前类对象是可以序列化的
- 父类没有实现序列化接口,子类实现,在父类提供无参构造函数时子类可以序列化
- 类中存在引用对象,当引用对象也实现了Serializable接口时这个类对象可以实现序列化
- 同一个对象多次序列化(之间有属性更新),会影响序列化(同一个对象序列化后会有编码,再次进行序列化时会识别到编码,不再进行序列化)
泛型
- 泛型:即参数化类型,将类型由原来具体的类型参数化,编译时会去掉泛型的类型参数(类型擦除)
List<String> left = new ArrayList<>();
List<Integer> right = new ArrayList<>();
System.out.println(left.getClass() == right.getClass()); //结果为true,都为list类型
List<Integer> list = new ArrayList<>();
//list.add("abcd"); 编译器报错
list.add(1);
//通过反射运行时添加字符串或浮点型可行,编译后代码运行时捕获不了类型信息
list.getClass().getMethod("add", Object.class).invoke(list, "abcd");
list.getClass().getMethod("add", Object.class).invoke(list, 1.2);
泛型特性
- 先检查(检查存储数据类型与定义泛型类型是否一致),后编译(编译后没有类型概念)
- 泛型不支持继承(比如将Object类赋值给String类,反过来也不行)
- 泛型的类型不能是基本数据类型
- 泛型的类型参数只能是类类型,不能是简单类型(类类型会识别每一个元素,简单类型会被当做一个整体类型值)
- 原始类型用于报表(各列类型不同),会很方便,但元素需要在代码中进行处理,可能会抛出运行时异常
- 原始类型应明确的指定具体类型,把类型检查的工作交给编译器来完成
反射
- Method类:提供一个类的方法的信息及访问类的方法的接口
- 当方法的参数是基本类型时,反射获取Method的参数类型也必须一致
- 如果调用的方法属于当前对象的父类,那么getDeclaredMethod获取不到Method,抛出异常
- getDeclaredMethod获取类自身声明的所有方法,newInstance通过反射创建新的类实例, invoke调用类中的方法
Class<Boss> clz = Boss.class;
Method method = clz.getDeclaredMethod("numeric", Integer.TYPE); //getDeclaredMethod(方法名,参数类)
method.invoke(clz.newInstance(), 19); //invoke(类实例,参数)
StringBuilder
- 使用“+”对String字符串进行拼接时,编辑器优化会使用StringBuilder的append方法进行拼接,但循环使用,会在每次循环时创建StringBuilder对象,严重影响性能
StringBuilder与StringBuffer的区别(StringBuffer线程安全适用于多线程,StringBuilder性能高适用于单线程)
StringBuilder StringBuffer 线程安全 线程不安全 线程安全(方法被synchronized修饰) 缓存区 不使用 使用(使用toStringCache进行缓存) 性能 高(远大于StringBuffer) 低
深浅拷贝
- 浅拷贝:如果拷贝对象属性是基本类型,拷贝基本类型的值,如果属性是内存地址(引用类型),拷贝内存地址,如果其中一个修改,则会影响另一个
- 深拷贝:原对象及引用对象一起拷贝,其中一个修改,不会影响另一个
- Cloneable接口:标记(该类可以克隆)接口,没有方法,clone方法是由Object提供的,如果类没有实现Cloneable接口,直接调用clone方法,则会抛出异常
- Object提供的clone方法是浅拷贝
- 深拷贝方法:自己new一个新对象
使用序列化和反序列化实现深拷贝
- 让对象实现Serializable接口(标记接口,不包含方法)
- 序列化:创建某些OutputStream(如FileOutputStream、ByteArrayOutputStream等),封装在ObjectOutputStream中,调用writeObject实现序列化
- 反序列化:创建某些InputStream(如FileInputstream、ByteArrayInputStream等)封装在ObjectInputStream内,调用readObject方法实现反序列化
- 实现深拷贝