序列化与反序列化
序列化:ObjectoutputStream:把Java中的对象,保存在磁盘中,相当于对象信息写出保存在文件中
反序列化:ObjectInputStream:把之前序列化输出的数据读取到内存程序中,相当于对象读取到程序
推荐一次序列化操作对应一次反序列化操作
注意:序列化输出的数据我们是看不懂的,我们需要后期通过反序列化技术把之前输出的数据恢复成对象,才能使用
基本案例
public class TestSerializable {
public static void main(String[] args) {
method1();//用于测试序列化
method2();//用于测试反序列化
}
//本方法用于测试反序列化
private static void method2() {
//1.定义在整个方法中都生效的局部变量,注意手动初始化值为null
ObjectInputStream in=null;
//2.由于方法可能抛出异常,所以需要完成try-catch-finally结构
try {
//3.创建反序列化输入流
in=new ObjectInputStream(
new FileInputStream("D:\\ready\\1.txt"));
//4.通过流对象反序列化恢复对象
Object o=in.readObject();
System.out.println(o);
System.out.println("恭喜你,反序列化成功");
}catch (Exception e){
System.out.println("反序列化失败");
e.printStackTrace();
}finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//本方法用于测试序列化
/*注意:序列化输出的数据我们是看不懂的
* 我们需要后期通过反序列化技术把之前输出的数据恢复成对象,才能使用*/
private static void method1() {
//1.定义一个在本方法中都生效的局部变量,注意手动初始化
ObjectOutputStream out=null;
try {
//3.创建流对象
out=new ObjectOutputStream(
new FileOutputStream("D:\\ready\\1.txt"));
//4.指定要序列化的对象
Student obj=new Student("海绵宝宝",3,"海里",'男');
//5.将刚刚创建好的学生类对象obj,使用序列化流out输出到指定文件1.txt中
out.writeObject(obj);
System.out.println("恭喜你,序列化成功");
}catch (Exception e){
System.out.println("序列化失败");
e.printStackTrace();
}finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*本类用于封装学生类*/
/*如果本类的对象想要被序列化输出,必须实现可序列化接口Serializable
* 否则会报错:java.io.NotSerializableException: cn.tedu.serializable.Student
*Serializable是一个空接口,里面一个方法都没有
* 作用是用作标记,标记这个类的对象可以被序列化 */
public class Student implements Serializable{
/*JVM会给每个要序列化输出的类分配一个唯一的UID
* 只要更改了这个类,自动生成的默认UID就会改变*/
//这个是我们手动提供的,写死的UID,版本永远是1l,不推荐
// private static final long serialVersionUID=1l;//不推荐
//1.定义学生类的相关属性并进行封装
private String name;//姓名
private int age;//年龄
private String addr;//住址
private char gender;//性别
//2.1创建本类的无参构造
public Student() {
System.out.println("Student的无参构造");
}
//2.1创建本类的全参构造
public Student(String name, int age, String addr, char gender) {
this.name = name;
this.age = age;
this.addr = addr;
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", addr='" + addr + '\'' +
", gender=" + gender +
'}';
}
//1.2给被封装的属性添加对应的get与set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
}
泛型
泛型怎么来的?--想要模拟数组的数据类型检查
泛型通常与集合一起使用,用来约束集合中元素的类型
泛型的好处:可以约束集合数据的类型,把报错的时机提取,而不是运行时才报错在向集合中添加元素时,会先检查元素的数据类型,不是要求的类型就编译失败
<type>--type的值应该如何写:
根据自己的业务自定义,但是type必须是引用类型,不能是基本类型
如果想写基本类型,请写,基本类型的包装类型。例:List<Integer> list2=new ArrayList();
泛型可以实现通用代码的编写,使用E表示元素的类型是Element元素
泛型的语法要求:如果在方法上使用泛型,必须在两处同时出现
一个是传入参数的类型为泛型,一个是返回值前的泛型类型,表示这是一个泛型方法
例:private static <E> void print(E[] e) { }
高效for循环/foreach循环
好处:比普通for循环写法简单且效率高
坏处:没有办法按照下标来操作值,只能从头到尾一次遍历即可
语法:for(1 2:3){循环体}
3-要遍历的数据 1-每轮遍历到的数据类型 2-变量名,可以随意起名
例:for (String arr : a) {
System.out.println(arr);}
Collection接口
![](https://i-blog.csdnimg.cn/blog_migrate/93dd2f64e826330a04558ce7882d565b.png)
方法:
public boolean add(E e) : 把给定的对象添加到当前集合中 。
public void clear() :清空集合中所有的元素。
public boolean remove(E e) : 把给定的对象在当前集合中删除。
public boolean contains(Object obj) : 判断当前集合中是否包含给定的对象。
public boolean isEmpty() : 判断当前集合是否为空。
public int size() : 返回集合中元素的个数。
public Object[] toArray() : 把集合中的元素,存储到数组中
List接口
1. List集合中的元素是可以重复的!
2. List集合中的元素是有序的!
3. List集合中的元素是带有索引值的 ‘
List独有的方法:
list.add(1,"小蝴蝶");//向指定索引处添加元素
list.indexOf("小蝴蝶");//获取元素第一次出现的索引值
list.lastIndexOf("小蝴蝶");//获取元素最后一次出现的位置
list.remove(5);//根据指定的索引值删除集合中的元素
list.get(3);//获取集合中指定的索引处的元素
list.set(7,"蝎子精");//修改指定索引处的元素为指定的元素蝎子精,会把被修改的值返回
案例:
/*本类用于测试List接口*/
public class TestList {
public static void main(String[] args) {
//1.创建List多态对象,注意List是一个接口,不可以实例化
List<String> list=new ArrayList<>();
//2.测试继承自Collection中的方法
list.add("大力娃");//向list中存入的数据
list.add("千顺娃");
list.add("头铁娃");
list.add("喷火娃");
list.add("喷水娃");
list.add("隐身娃");
list.add("小紫娃");
System.out.println(list);
// list.clear();//清空集合中的所有元素
System.out.println(list.contains("喷火娃"));//true
System.out.println(list.equals("喷水娃"));//false
System.out.println(list.isEmpty());//false,判断集合是否为空
System.out.println(list.remove("小紫娃"));
System.out.println(list.size());//6
System.out.println(Arrays.toString(list.toArray()));//将集合转为数组
//3.测试list接口自己的方法,由于list是有序的,所以可以根据索引来操作集合中的元素
list.add("小蝴蝶");//默认追加
System.out.println(list);
list.add(1,"小蝴蝶");//向指定索引处添加元素
list.add(3,"蛇精");
System.out.println(list);
System.out.println(list.indexOf("小蝴蝶"));//获取元素第一次出现的索引值
System.out.println(list.lastIndexOf("小蝴蝶"));//获取元素最后一次出现的位置
System.out.println(list.remove(5));//根据指定的索引值删除集合中的元素
System.out.println(list);
System.out.println(list.get(3));//获取集合中指定的索引处的元素
System.out.println(list);
System.out.println(list.set(7,"蝎子精"));//修改指定索引处的元素为指定的元素蝎子精,会把被修改的值返回
System.out.println(list);
//4.测试集合间的操作
List<String> list2=new ArrayList<>();
list2.add("1");
list2.add("2");
list2.add("3");
list2.add("4");
System.out.println(list2);//打印查看集合内容
System.out.println(list.addAll(list2));
System.out.println(list.addAll(1,list2));
System.out.println(list);
System.out.println(list.containsAll(list2));//true
System.out.println(list.removeAll(list2));
System.out.println(list);
Iterator<String> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}