更改类名快捷键:alt+enter-->点Rename File(前提先改好名称,报错了再用快捷键)
生成get,set,toStringg,构造器等的快捷键:alt+insertScrelk(然后选择需要生成的方法
生成try/catch/finally,do/while,if/else...的快捷键:Ctrl+alt+t
一、常用类
1、String类
2、正则表达式
3、Object类
4、包装类
包装类wrapper:每一个基本类型都与之对应的对象(包装类型) 面向对象编程:操作对一定比操作基本类型简单,主要是提供了强大的功能为我们使用。 byte -- Byte short -- Short int --- Integer long -- Long float -- Float double -- Double char -- Character boolean -- Boolean
1、转换关系 --- 不需要我们做,但要知道 基本类型 -- > 包装类 Integer.valueOf(int i) 包装类 -- > 基本类型 Integer.intValue() 基本类型 -- > String String.valueOf(String s) String --> 基本类型 Integer.parseInt(String s) 包装类 --> String Integer.toString String --> 包装类 Integer.valueOf(String s)
//主方法:程序的入口-->读代码的入口,从main的第一行开始看起 public static void main(String[] args) { //基本类型--包装类 int i = 10; Integer integer = Integer.valueOf(i); System.out.println(integer); //包装类 - - 基本数据类型 Integer integer1 = 113; int a = integer1.intValue(); System.out.println(a); //String -- 基本数据类型 //String s = "123d";//NumberFormatException;数据格式化异常 String s = "123"; int as =Integer.parseInt(s); System.out.println(as); //基本数据类型 -- String int ad = 34; String ss = Integer.toString(ad); System.out.println(ss); System.out.println(ss.getClass()); //String -- 包装类 String s1 = "123"; Integer integer2 = Integer.valueOf(s1); System.out.println(integer); System.out.println(integer.getClass()); //包装类 -- String Integer integer3 = 123; String s2 = integer3.toString(); System.out.println(s2); System.out.println(s2.getClass()); }
2、自动装箱和拆箱 基本数据类型和包装类的转换,就是自动拆箱和装箱的过程
装箱:基本数据类型转换成包装类
拆箱:包装类转换成基本数据类型
5、时间日期
二、集合
1、集合:各种各样的数据结构 --程序 = 算法 + 数据结构(存储数据的结构)
-
数组:存储的是相同元素类型的元素
-
<E>:泛型(指定当前集合的存储元素类型) *1、Collection:集合的根接口
public static void main(String[] args){ //测试Collection常用方法 //格式:Collection<数据类型> collection= new ArrayList<数据类型(可写可不写)>(); //创建对象,向上转型 Collection<Integer> collection= new ArrayList<Integer>(); //add(添加的值):给集合添加值 collection.add(12); collection.add(13); collection.add(14); System.out.println(collection); //集合.contains(字符串):判断集合是否有该字符串(有true,反之false) System.out.println(collection.contains(13));//true //集合.containsAll(另一个集合):判断集合是否含有另一个集合的全部(是true,反之false) Collection<Integer> collection1 = new ArrayList<>(); collection1.add(12); collection1.add(13); System.out.println(collection.containsAll(collection1));//true //集合.size():集合大小,指的是元素个数,不是集合容量大小 System.out.println(collection.size());//3 //集合.addAll(集合):给集合添加另一个集合的内容 collection.addAll(collection1); System.out.println(collection);//[12, 13, 14, 12, 13] //集合.isEmpty():判断该集合是否为空(空true,反之false) System.out.println(collection.isEmpty());//false //集合.remove(删除元素):删除集合对应元素 System.out.println("删除前"+collection);//[12, 13, 14, 12, 13] System.out.println(collection.remove(12));//true System.out.println("删除后"+collection);//[13, 14, 12, 13] //集合.removeAll(删除的集合):删除两个集合相同的元素 System.out.println("大集合"+collection);//[13, 14, 12, 13] System.out.println("小集合"+collection1);//[12, 13] System.out.println(collection.removeAll(collection1));//true System.out.println("删除后"+collection);//[14] //集合.retainAll(保留的元素或集合):保留当前元素,删掉其他元素 Collection<String> c = new ArrayList<>(); c.add("a"); c.add("b"); c.add("c"); Collection<String> o = new ArrayList<String>(); o.add("a"); o.add("b"); System.out.println(c.retainAll(o));//true System.out.println(c);//[a, b] //集合.clear();删除所有元素 System.out.println("原来集合"+c);//[a, b] c.clear(); System.out.println("删除后的集合"+c);//[] //将Integer集合转换成Integer类型数组 Collection<Integer> col = new ArrayList<>(); col.add(1); col.add(2); col.add(3); //方式一:toArray(T[] t) Integer[] integers = col.toArray(new Integer[col.size()]); Integer[] integers1 = col.toArray(new Integer[]{}); System.out.println(Arrays.toString(integers1));//[1, 2, 3] System.out.println(Arrays.toString(integers));//[1, 2, 3] System.out.println(integers.getClass());//Integer //方式二:toArray(); Object[] o1 = col.toArray(); Integer[] integers2 = new Integer[o1.length]; for (int i = 0; i < o1.length; i++) { integers2[i] = (Integer) o1[i]; } System.out.println(Arrays.toString(integers2));//[1, 2, 3] System.out.println(integers2.getClass());//class [Ljava.lang.Integer; }
2、List:有序(自然顺序,元素存储的先后顺序。非排序)可重复
数组(队列)和堆:先进先出 ,
栈:先进后出
(1)、ArrayList -底层Object类型的数组 ——线程非安全 ——默认初始化容量为10 ——扩容实现:数组的复制 ——扩容算法:1.5倍 ——截取的数组共用一块资源 ——做查询快 (2)、LinkedList ——底层是链表实现,内部封装一个静态内部类Node ——做修改快,因为是指针实现 (3)、Stack
队列:先进后出(栈)
(4)、Vector 和ArrayList原来相同,但线程安全,效率低,不常用
public static void main(String[] args) { /* 1、默认初始容量是10 2、扩容机制 3、初始化过程 * */ //1、初始化过程 ArrayList() ArrayList(int i):i表示容量 ArrayList<String> list = new ArrayList<>();//初始化了一个无长度的空数组 ArrayList<String> list1 = new ArrayList<>(15);//初始化一个长度为15的数组 System.out.println(list.size());//0 System.out.println(list1.size());//0 //2、扩容机制:初始容量(不确定):根据元素数量去计算,当没有元素时。默认为10 //扩容机制:x + x >>1,x的1.5倍 //扩容的实现:数组的复制 list.add("python"); list.add("java"); list.add("c"); list.add("c++"); //截取字符串,数组.subList(起始值,目标值),截取的子串和原串共用一块资源 List<String> l = list.subList(1,3);//左闭右开 System.out.println(l);//[java, c] //修改元素 for (int i = 0; i < l.size(); i++) { l.set(i,l.get(i)+"1"); } System.out.println(l);//[java1, c1] System.out.println(list);//[python, java1, c1, c++] }
集合排序问题:
集合的排序规则 1、如果要对一个对象进行排序,则该对Comparable象必须实现 2、重写comparable方法设置排序的规则 3、根据返回值确定大于小于等于,所对应的是正数,负数,零 集合的临时排序规则 1、在sort方法的第二个参数采用匿名内部类的方法 针对于List
自定义类
public class Person implements Comparable<Person> { private String name; private Double Salary; public Person(String name, Double salary) { this.name = name; Salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getSalary() { return Salary; } public void setSalary(Double salary) { Salary = salary; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", Salary=" + Salary + '}'; } @Override public int compareTo(Person person) { /* //先获取本对象 Double x = this.Salary; //获取参数对象 Double y = person.Salary; //获取返回值 int z = x > y ? 1 : ((x == y) ? 0 : -1);*/ return compare(this,person); } //自定义方法 public static int compare(Person p1,Person p2){ return p1.Salary > p2.Salary ? 1: ((p1.Salary == p2.Salary)?0:-1); } }
测试类
//测试Person类的alary排序 ArrayList<Person> persons = new ArrayList<>(); persons.add(new Person("a",20000.0)); persons.add(new Person("b",10000.0)); persons.add(new Person("c",45000.0)); System.out.println("排序前:"+persons); Collections.sort(persons); System.out.println("排序hou:"+persons); //测试临时排序规则 /*Collections.sort(persons, new Comparator<Person>() { @Override public int compare(Person person, Person t1) { return person.getSalary() < t1.getSalary() ? 1 : (person.getSalary().equals(t1.getSalary()) ? 0 : -1); } });*/ //lambda格式,1.8的新特性 Collections.sort(persons, (person, t1) -> person.getSalary() < t1.getSalary() ? 1 : (person.getSalary().equals(t1.getSalary()) ? 0 : -1)); System.out.println("sd:"+persons); Collections.sort(persons); System.out.println("排序hou:"+persons);
队列和双端队列
public static void main(String[] args) { //创建队列对象 Queue<Object> queue = new LinkedList<>(); //入队 queue.offer("a"); queue.offer("b"); queue.offer("c"); queue.offer("d"); System.out.println(queue);//[a, b, c, d] //取出第一个 System.out.println(queue.poll());//a System.out.println(queue);//[b, c, d] System.out.println(queue.size());//3 System.out.println(queue.remove());//b,从开始元素删除 System.out.println(queue);//[c, d] queue.clear();//全部清除 System.out.println(queue);//[] System.out.println("============="); //双端队列 Deque<Object> s = new LinkedList<>(); //测试双端队列进出 s.offer(1); s.offerFirst(2); s.offerFirst(3); s.offerLast(4); s.offerLast(5); System.out.println(s);//[3, 2, 1, 4, 5] System.out.println(s.pollLast());//5 System.out.println(s.pollFirst());//3 System.out.println(s);//[2, 1, 4] System.out.println(s.peekLast());//4 System.out.println(s.peekFirst());//2 System.out.println(s);//[2, 1, 4] }
3、set:无序 不可重复
1、HashSet 2、TreeSet 3、LinkedHashSet
/*——HashSet:底层是HashMap ——LinkedHashSet:让无序HashSet变有序(有Link开头的就是有序) ——TreeSet:排序 */ public static void main(String[] args) { //set集合测试 HashSet<Integer> set = new HashSet<>(); set.add(1); set.add(2); set.add(3); set.add(1);//有相同的元素自动去重 System.out.println(set);//[1, 2, 3] //测试LinkedHashSet LinkedHashSet<Integer> s = new LinkedHashSet<>(); s.add(2); s.add(3); s.add(4); s.add(2);//有相同的元素自动去重 System.out.println(s);//[2, 3, 4] //测试TreeSet TreeSet<Integer> ger = new TreeSet<>(); ger.add(5); ger.add(7); ger.add(6); ger.add(5);//有相同的元素自动去重 System.out.println(ger);//[5, 6, 7] }
4、迭代器 (iterator)
专门用来遍历集合的,遍历集合有四种方式
面试题:增强for循环原理是迭代器,而迭代器是专门用来遍历集合的, 但数组不是集合,为什么增强for循环可以遍历数组? 使用增强for循环遍历数组时,会解析成普通的for循环。但增强for循环遍历集合时,会解析为迭代器 */ public static void main(String[] args) { //迭代器,专门用来遍历集合 ArrayList<Integer> s = new ArrayList<>(); //给数组添加元素 for (int i = 0; i < 5; i++) { s.add(((int)(Math.random()*10))); } System.out.println(s); //基本for循环 for (int i = 0; i < s.size(); i++) { System.out.println(s.get(i)); } //增强for循环 System.out.println("=====增强for循环======="); for(Integer g : s){ System.out.println(g); } //集合.foreach方法 System.out.println("-------foreach方法---------"); s.forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } }); //迭代器 System.out.println("------迭代器-------"); //先获取迭代器对象,集合.iterator() Iterator<Integer> iterator = s.iterator(); while(iterator.hasNext()){//判断是否还有下一个元素 //System.out.println(iterator.next());//0 2 1 9 4,获取值 if (iterator.next()>5){ //s.remove(iterator.next());//运行错误,迭代器遍历出来的必须因迭代器的方法删除 System.out.println(iterator.next()); } } } }
5、map:以键值对存储,无序,键值唯一,值不唯一
Map:跟接口 1、特点:存储是k-v键值对存储,无序,key值唯一 2、实现类:HashMap,LinkedHashMap,TreeMap,HashTable HashTable和HashMap的区别:HashTable是线程安全的。 3、常用方法: 1.集合.put(键值,值):给集合添加数据 2.集合.size():集合大小 3.集合.inEmpty():判断集合是否为空 4.集合.containsKey(键值):判断集合是否有该键值(有true,反之false) 5.集合.containsValue(值):判断集合是否有该值(有true,反之false) 6.集合.get(键值):根据键值获取对应的值 7.集合.remove(键值):根据键值删除对应值 8.集合.putAll(另一个集合);添加另一个集合数据 9.集合.keySet();只获取键值' 10.集合.value();只获取值 11.集合.equals(另一个集合):判断两个集合是否相同 12.集合.replace():根据键值替换值 13.集合.replace(建,值,新值):根据键和值替换值 14.集合.clear():清除所有元素
15.集合.entrySet():遍历集合,获取单独的k值或V值
4、原理: -怎么初始化 1.构造方法中没有做任何的数组初始化 2.负载因子 -默认为0.75f -元素的容量 xx.size/capacity,是一个最优解,为了增加HashMap的性能 3.最大容量:默认值2^30
-put的原理-HashMap的存储原理? 0.put方法会初始化为桶Node数组大小,默认16 1.put方法存储时,会先计算key的hashCode方法返回int值,根据hash算法确定当前元素key在位桶中的位置 2.如果该位置无元素,则直接放入数组 3.如果当前位置上有元素,则产生hash冲突(hash碰撞) 4.产生hash冲突后,根据key的equals方法进行判断key是否相等,如果相等,则将key对应的值覆盖 5.如果key的equals方法不相等,则采用尾插法将元素插入链表的尾部 6.当链表的长度大于7时,链表转为红黑数进行存储 7.当位桶Node数组大于指定容量(指结合负载所计算出来的容量)时,扩容 8.扩容为原来的2倍 建议每个实体类都增加加hashCode方法和equals方法
public static void main(String[] args) { //创建map类 HashMap<Integer,String> map = new HashMap<>(); HashMap<String, Integer> smp = new HashMap<>(); //1、集合.put(键值,值):给集合添加数据 map.put(1,"a"); map.put(2,"b"); map.put(3,"c"); map.put(3,"d");//建值相同会覆盖前面的值 System.out.println(map);//{1=a, 2=b, 3=d} //2.集合.size():集合大小 System.out.println(map.size());//3 //3.集合.inEmpty():判断集合是否为空 System.out.println(map.isEmpty());//false,不是空返回false //4.集合.containsKey(键值):判断集合是否有该键值(有true,反之false) //5.集合.containsValue(值):判断集合是否有该值(有true,反之false) System.out.println(map.containsKey(1));//true System.out.println(map.containsValue("f"));//false //6.集合.get(键值):根据键值获取对应的值 System.out.println(map.get(1));//a //7.集合.remove(键值):根据键值删除对应值并返回该值 //7.集合.remove(键值,值):根据键和值删除 System.out.println(map.remove(3));//d System.out.println("删除后的集合"+map);//{1=a, 2=b} //8.集合.putAll(另一个集合);添加另一个集合数据 HashMap<Integer, String> mps = new HashMap<>(); mps.put(2,"w"); mps.put(5,"w"); mps.put(6,"w"); System.out.println("添加前"+map);//{1=a, 2=b} map.putAll(mps); System.out.println("添加后"+map);//{1=a, 2=w, 5=w, 6=w} //9.集合.keySet();只获取键值 //10.集合.value();只获取值 System.out.println(map.keySet());//[1, 2, 5, 6] System.out.println(map.values());//[a, w, w, w] //11.集合.equals(另一个集合):判断两个集合是否相同 System.out.println(map.equals(mps));//false //12.集合.replace():根据键值替换值 System.out.println("==========="); System.out.println(map);//{1=a, 2=w, 5=w, 6=w} map.replace(2,"y"); System.out.println(map);//{1=a, 2=y, 5=w, 6=w} //13.集合.replace(建,值,新值):根据键和值替换值 map.replace(1,"a","k"); System.out.println(map);//{1=k, 2=y, 5=w, 6=w} //forEach() map.forEach(new BiConsumer<Integer, String>() { @Override public void accept(Integer integer, String s) { System.out.println(integer); System.out.println(s); } }); //14.集合.clear():清除所有元素 //map.clear(); //System.out.println(map);//{} //15.集合.entrySet() Set<Map.Entry<Integer, String>> entries = map.entrySet(); for(Map.Entry<Integer,String> entry:entries){ System.out.println("key "+entry.getKey());//获取key值 System.out.println("value "+entry.getValue());//获取value值 } }
三、异常处理机制
异常处理机制:如何处理异常 1、抛出异常:方法的后面加throws (一个或者多个);一般用于测试时使用,为了代码的可读性
2、抓住异常: try{可能出现的异常代码}catch(抓住的异常对象){对异常处理的代码} try{}catch(){}finally {无论是否发生异常都会执行的代码} 3、处理异常,如果有多个异常可以直接抛共同的父类异常 4、通过异常对象可以输出以下常用信息:消息,原因,堆栈信息 5、自定义异常:继承Exception类,重写其对应的方法
public class TestException { //public static void main(String[] args) throws InterruptedException {//抛出的异常 //public static void main(String[] args) throws Exception {//抛出多个异常有共同的父类的异常 public static void main(String[] args) { //非检测异常 int[] i = new int[4]; //System.out.println(i[7]);//ArrayIndexOutOfBoundsException //检测异常 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("代码了"); } try { FileInputStream fileInputStream = new FileInputStream("12"); } catch (FileNotFoundException e) { //e.printStackTrace(); System.out.println("没有找到文件"); }finally { System.out.println("有没有异常我都会执行"); } } }
四、IO流
什么是io流:
io表示有两个单词缩写:input输入;output输出
io流的作用:就是对文件的内容进行操作
-
输入流 输出流 字节流抽象类 inputStream outputStream 字节流 文件流 fileInputStream fileOutputStream 字节流 缓冲流 BuferedInputStream BuferedOutputStream 字节流 对象流 ObjectInputStream ObjectOutputStream 字节流 内存流 ByteArrayInputStream ByteArrayOutputStream 字符流 字符抽象类 Reader Writer 字符流 文件流 fileReader fileWriter 字符流 缓冲流 BuferedReader BufereWriter 字符流 转换流 InputStreamReader OutputStreamWriter
1、File文件操作
File:表明文件抽象路径名对象 路劲问题: 1.绝对路径:从磁盘根目录开始 2.相对路径: 技巧:所有的相对路径如果忘了,从绝对路径开始依次删除到文件前面,直到测试结果值正确为止 3.面试题: \\(两个反斜杠)和/(一个正斜杆)表示路径有什么区别?兼容性问题 \\是Windows独有的 /在任何操作系统上都能识别,建议使用
public static void main(String[] args) { //File cd = new File("文件对象"); //绝对路径 File file = new File("D:\\2022Java\\JavaProject\\Day719\\src\\com\\shy\\day721\\file\\TestFile.java"); System.out.println(file.exists());//true //相对路径 File file1 = new File("C:\\Users\\Admin\\Desktop\\Test.txt"); System.out.println(file1.exists());//true //创建文件 try { System.out.println(file1.createNewFile()); } catch (IOException e) { e.printStackTrace(); } //判断文件或路径是否存在 System.out.println(file1.exists());//true //判断文件是否可读 System.out.println(file1.canRead());//true //判断文件是否可写 System.out.println(file1.canWrite());//true //路径长度 System.out.println(file1.length());//114 //判断文件是否隐藏 System.out.println(file1.isHidden());//false //判断是否是文件 System.out.println(file1.isFile());//true System.out.println("===================="); //获取绝对路径 System.out.println(file1.getAbsolutePath());//C:\Users\Admin\Desktop\Test.txt //获取路径 System.out.println(file1.getPath());//C:\Users\Admin\Desktop\Test.txt //获取文件名 System.out.println(file1.getName());//Test.txt //获取文件最后一次修改的时间,毫秒 System.out.println(file1.lastModified());//1657021860025 //删除文件 System.out.println(file1.delete()); //创建文件 File file2 = new File("C:\\Users\\Admin\\Desktop\\T.txt"); try { System.out.println(file2.createNewFile()); } catch (IOException e) { //e.printStackTrace(); System.out.println("已有该文件"); } //修改文件名 }
2、IO流
IO流: Input(序列化):输入 文件->控制台 读取文件叫输入 output(反序列化):输出 控制台->文件 写出文件叫输出
分类: 1、字节流(以byte进行读写)和字符流(以字符进行读写)、 以Stream结尾的都是字节流,以Reader和writer结尾的都是字符流
2、低级流(节点流)和高级流(过滤,载体流) 高级流以低级流为载体的。 常用IO:FIS\FOS(序列化和反序列化) BIS\BOS(缓冲区) OIS\OOS() OSW\ISW PW\BP
单元测试: 测试代码一种,可以单独运行一个方法(一个方法就是一个单元)
1、FIS\FOS(序列化和反序列化)
public class TestFISAadFOS { //属性 File file; FileOutputStream fos; FileInputStream fis; @Before//Test运行之前必须执行的方法 public void getFile() throws IOException { file = new File("src/com/shy/day724/io/java.txt"); file.createNewFile(); } @Test//输入(读) public void Test1() throws IOException { fos = new FileOutputStream(file); //写入write(int i):写入int值的低8位,对应ASCll码 //write(byte[] bus):写入byte[] fos.write("hello world".getBytes()); } @Test//读出 public void Test2() throws IOException { fis = new FileInputStream(file); int i = -1; byte[] bytes = new byte[1024]; if ((i=fis.read(bytes))!=-1) System.out.println(new String(bytes)); } @Test//复制文件 public void fileCopy() throws IOException { //读取 //String s = file.getAbsolutePath(); fis = new FileInputStream(file); file = new File("src/com/shy/day724/io/java_copy.txt"); fos = new FileOutputStream(file,true); int i = -1; //单个 while ((i=fis.read())!=-1){ System.out.println((char) i); fos.write(i); } //多个 /*byte[] bytes = new byte[1024]; if ((i=fis.read(bytes))!=-1) { fos.write(bytes); }*/ } @After//每一个Test运行完之后就必须运行的内容 public void close() throws Exception{//可能有异常 //非空判断,关闭流,释放资源 if (fis != null) fis.close(); if (fos != null) fos.close(); } }
2、BIS\BOS(缓冲区)
/* 缓冲区: BIS:BufferedInputStream BOS:BufferedOutputStream */ public class TestBISAndBOS { //属性 File file; BufferedInputStream bis; BufferedOutputStream bos; @Before public void getFile() { file = new File("src/com/shy/day724/io/bos.txt"); } @Test public void Write() throws IOException { bos = new BufferedOutputStream(new FileOutputStream(file)); bos.write("hello worlds".getBytes());//写入缓冲区 bos.flush();//刷新了才能将写的内容写到文件中 } @Test public void Read() throws IOException { bis = new BufferedInputStream(new FileInputStream(file)); int i = -1; byte[] bytes = new byte[1024]; //if ((i=bis.read(bytes))!=-1) System.out.println(bytes); /* System.out.println(bis.read(bytes));//14*/ System.out.println(new String(bytes)); /*while((i=bis.read(bytes))!=-1){ System.out.println(new String(bytes));//hello worlds }*/ } @Test public void fileCopy() throws IOException { bis = new BufferedInputStream(new FileInputStream(file)); file = new File("src/com/shy/day724/io/boss.txt"); bos = new BufferedOutputStream(new FileOutputStream(file)); int i = -1; /* while ((i=bis.read())!=-1){ bos.write(i); }*/ byte[] bytes = new byte[1024]; if ((i = bis.read(bytes)) != -1) { System.out.println(new String(bytes)); } } @After public void close() throws IOException { //当发生流的链接时,关闭流最外层流即可 //关闭流也有刷新缓冲区的作用 if (bos != null) bos.close(); if (bis != null) bis.close(); } }
3、OIS\OOS
OOS:ObjectOutputStream OIS:ObjectInputStream 难点:对象序列化和反序列化:目的:能将对象保存在磁盘(或外部设备)中 序列化:对象-->字节序列 反序列化:字节序列-->对象
问题: 1、如何进行序列化和反序列化? -实现序列化和反序列化的对象必须实现Serializable(不需要任何实现,仅表示当前对象实现序列化和反序列化) -序列化使用writeObject(Object object) -反序列化用ReadObject() 2、反序列化时的两种存在问题? -序列化后改变文件内容:会抛出异常StreamCorruptedException,即使改变回来也会报错 -序列化改变对象属性名称:会抛出InvalidClassException,改回来就可以了 private static final long serialVersionUID = -5753899536500384418L;序列化接口版本号 解决兼容性问题:在反序列化时如果改变对象属性,程序不会报错,只不过被改变的属性反序列化后没有值 3、对象瘦身 问题:transient:专门针对对象的瘦身,表示不需要序列化的对象可以省略属性的序列化,减少字节序列的生成
Person类
public class Person implements Serializable { //身份证号 private static final long serialVersionUID = -5753899536500384418L; private String name = "雨"; private Integer age = 24; @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
public class TestOOSAndOIS { //属性 File file; ObjectOutputStream oos; ObjectInputStream ois; @Before public void getFile(){ file = new File("src/com/shy/day724/Person.txt"); } @Test public void TestPerson() throws IOException, ClassNotFoundException { //序列化 oos = new ObjectOutputStream(new FileOutputStream(file)); Person person = new Person(); oos.writeObject(person); } @Test public void TestPerson1() throws IOException, ClassNotFoundException { //反序列化 ois = new ObjectInputStream(new FileInputStream(file)); Object o = ois.readObject(); System.out.println(o); } @After public void close() throws IOException { if (oos!=null)oos.close(); if (ois !=null)ois.close(); } }
4、OSW\ISR
/* OSW:OutputStreamWrite */ public class TestOSWAndISR { //属性 File file; OutputStreamWriter osw; InputStreamReader isr; @Before public void getFile(){ file = new File("src/com/shy/day724/osw.txt"); } @Test//写 public void write() throws IOException { osw = new OutputStreamWriter(new FileOutputStream(file)); osw.write("hello world"); } @Test//读取(输入) public void read() throws IOException { isr = new InputStreamReader(new FileInputStream(file)); int i = -1; /*if((i=isr.read())!=-1){ System.out.println(i); }*/ char[] bytes = new char[1024]; isr.read(bytes);//将内容放入字符数组中 System.out.println(new String(bytes)); } /*2.ISR和OSW实现文件的复制*/ @Test//复制 public void fileCopy() throws IOException { //获取内容 isr = new InputStreamReader(new FileInputStream(file)); //新文件 file = new File("src/com/shy/day724/osw_copy.txt"); osw = new OutputStreamWriter(new FileOutputStream(file)); int i =-1; char[] s = new char[1023]; if ((i=isr.read(s))!=-1){ System.out.println(s); osw.write(s); } } @After//关闭流 public void close() throws IOException { if (osw!=null)osw.close(); if (isr!=null)isr.close(); } }
5、PW\BP
PW:PrintWriter 字符流 -autoFlush 自动刷新 一个布尔值 BR:BufferedReader */ public class TestPWAndBR { public static void main(String[] args) throws Exception { File file = new File("src/com/shy/day724/io/WB.txt"); PrintWriter pw = new PrintWriter(new FileOutputStream(file)); pw.println(2); pw.println(2); pw.println(2); pw.println(2); pw.println(2); //pw.flush(); pw.close(); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file))); int read = br.read(); int i =-1; char[] chars = new char[1024]; br.read(chars);//将文件内容写入字符数组 System.out.println(chars); /*if ((i=br.read(chars))!=-1){ System.out.println(chars); }*/ } }
五、多线程
-
1、线程和进程
-
-进程:一个正在运行的应用程序(微信,扣扣...)
-
-线程:是程序执行的最小单位 *
-
2、并发和并行
-
-并发:交替进行,同一时刻只能执行一个线程,多条线程相互交替完成一个任务
-
-并行:同时进行
-
3、线程生命周期
-
-起始状态:创建线程对象 --new
-
-就绪状态:线程对象.start
-
-运行状态:执行run方法
-
-阻塞状态:线程运行被中断
-
-结束状态:run方法执行完毕或线程强制停止
-
4、线程创建方式
-
1、实现Runnable接口,重写run方法
-
2、继承Thread类,重写run方法
-
3、实现Callable接口,写call方法(有返回值)
六、反射
1、反射的几种方式(反射:框架的灵魂!)
测试的类
public class Persons { public String name; private Integer age; public void run() { System.out.println("run的方法"); } private void sleep() { System.out.println("sleep的方法"); } private Integer sum(Integer a, Integer b) { return a + b; } @Override public String toString() { return "Persons{" + "name='" + name + '\'' + ", age=" + age + '}'; } /* static{ System.out.println("静态代码块"); } { System.out.println("非静态代码块"); } public Persons() { System.out.println("构造方法"); }*/ }
1、创建Class对象的三种方式()
(1)类名.class:都不初始化 (2)Class.forName("全类名"):只初始初始化静态代码块 (3)对象.getClass();初始化代码块和构造方法
Class类常用方法: 1、获取属性 -- Field
2、获取构造方法 -- Constructor
3、获取方法 -- Method
public class TestReflect { @Test//类.class public void createRun(){ Class pc = Persons.class; System.out.println(pc);//class com.shy.day725.refect.Persons,是类 } @Test//Class.forName("全类名") public void createRun1() throws ClassNotFoundException { Class aClass = Class.forName("com/shy/day725/reflect/Persons"); } @Test//对象.getClass(); public void createRun2() throws ClassNotFoundException { Persons persons = new Persons(); Class aClass = persons.getClass(); } @Test//测试三种方法创建的方式的区别: public void BooleanClass() throws ClassNotFoundException { System.out.println("=+++"); Class pc = Persons.class; System.out.println("============"); Class as = Class.forName("com.shy.day725.reflect.Persons"); System.out.println("------------"); Persons p = new Persons(); Class ac = p.getClass(); //System.out.println(as==pc); //System.out.println(as==ac); } }
2、反射获取成员并操作成员
@Test public void Test1() throws Exception { //获取Class对象 Class<Persons> pc = Persons.class; //获取属性对象Field[] Field[] fields = pc.getFields(); for(Field file:fields){ System.out.println(file);//只获取public修饰的属性 } //获取单个属性对象 Field name = pc.getField("name"); System.out.println(name); //对属性重新赋值 Persons persons = pc.newInstance(); System.out.println(persons);//Persons{name='null', age=null} //下面对象重新赋值发生在运行期 name.set(persons,"雨"); System.out.println(persons);//Persons{name='雨', age=null} } @Test public void Test1() throws Exception { Class<?> as = Class.forName("com.shy.day725.reflect.Persons"); //暴力获取对像 Field[] fields = as.getDeclaredFields(); System.out.println(fields); for (Field file:fields){//遍历才能显示出全部属性 System.out.println(file); } //暴力获取一个private属性 Field age = as.getDeclaredField("age"); System.out.println(age); //修改私有属性 Persons o = (Persons)as.newInstance(); age.setAccessible(true);//暴力反射,如果不写,会报异常 age.set(o,12); System.out.println(o);//Persons{name='null', age=12} }
3、反射暴力获取方法并且操作方法
@Test public void Test1() throws Exception { Class<?> as = Class.forName("com.shy.day725.reflect.Persons"); //暴力获取对像 Field[] fields = as.getDeclaredFields(); System.out.println(fields); for (Field file : fields) {//遍历才能显示出全部属性 System.out.println(file); } //暴力获取一个private属性 Field age = as.getDeclaredField("age"); System.out.println(age); //修改私有属性 Persons o = (Persons) as.newInstance(); age.setAccessible(true);//暴力反射,如果不写,会报异常 age.set(o, 12); System.out.println(o);//Persons{name='null', age=12} } @Test public void Text() throws Exception { Class<Persons> ps = Persons.class; Method[] methods = ps.getMethods(); for (Method method : methods) { System.out.println(method); } //getMethon获取单个方法对象时,考虑方法重载,也就是参数问题,这里的第二个数为可变参数(可以为多个,也可以没有) //传参的内容为:参数的类型的Class对象 //show(String s) Method run = ps.getMethod("run"); Persons persons = ps.newInstance(); run.invoke(persons);//run的方法 } @Test//暴力获取方法们 public void test3() throws Exception { //发射对象.getDeclaredMethod("方法名",参数类型.class(可有可无)) Class<Persons> cls = Persons.class; Method run = cls.getDeclaredMethod("run"); System.out.println(run);//public void com.shy.day725.reflect.Persons.run() run.setAccessible(true); Persons person = cls.newInstance(); run.invoke(person);//输出方法里面的输出内容(run的方法),调用该方法 //测试sum Integer.class 表示该方法参数类型的class对象, Method sum = cls.getDeclaredMethod("sum", Integer.class, Integer.class); sum.setAccessible(true);//有这个才能给方法赋值 Integer invoke = (Integer) sum.invoke(person, 100, 300); System.out.println(invoke);//400 Method sleep = cls.getDeclaredMethod("sleep"); sleep.setAccessible(true); System.out.println(sleep);//private void com.shy.day725.reflect.Persons.sleep() sleep.invoke(person);//sleep的方法 } }
七、设计模式
1、单例模式
public class LanShi { public static void main(String[] args) { //调用懒汉式 Order od = Order.getInstance(); Order od1 = Order.getInstance(); System.out.println(od==od1); } } //懒汉式(调用才创建叫懒汉式) class Order{ //私有化构造器 private Order(){ } //声明当前类对象,没有初始化,此对象必须声明为static private static Order instance = null; //声明public,static的方法返回当前类对此 public static Order getInstance(){ if (instance == null){ instance = new Order(); } return instance; } } //饿汉式(没调用就创建叫饿汉式) class Order1{ //私有化构造器 private Order1(){ } //声明当前类对象,没有初始化,此对象必须声明为static private static Order1 instance = new Order1(); //声明public,static的方法返回当前类对此 public static Order1 getInstance(){ return instance; } }