十十五天笔记总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了十十五天笔记总结相关的知识,希望对你有一定的参考价值。
1. LineNumberReader: *public int getLineNumber():获取行号 *public void setLineNumber(int lineNumber):设置起始行号 String readLine():读取一行 案例:读取文件,每次读取一行打印并且加上行号 packagecom.edu_01; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; /** * 1. LineNumberReader: *public int getLineNumber():获取行号 *public void setLineNumber(int lineNumber):设置起始行号 String readLine():读取一行 案例:读取文件,每次读取一行打印并且加上行号 * */ public class LineNumberReaderDemo { publicstatic void main(String[] args) throws IOException { //创建LineNumberReader对象 //publicLineNumberReader(Reader in) LineNumberReaderlnr = new LineNumberReader(new FileReader("a.txt")); //默认起始行号从0开始 //设置其实行号为从10开始 lnr.setLineNumber(10); //一次读取一行 Stringline; while((line = lnr.readLine())!=null) { //打印每一行的行号和内容 System.out.println(lnr.getLineNumber()+":"+line); } //关流 lnr.close(); } } 2.操作基本数据类型的流 * 可以操作基本类型的流对象。 *DataInputStream:读数据 *DataOutputStream:写数据 * 案例:给流中写基本类型的数据,并且读取 注意: * 读写顺序必须一致,否则数据有问题。 package com.edu_02; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * 2.操作基本数据类型的流 * 可以操作基本类型的流对象。 *DataInputStream:读数据 *DataOutputStream:写数据 案例:给流中写基本类型的数据,并且读取 注意: * 读写顺序必须一致,否则数据有问题。 * */ public class DataOutputStreamDemo { publicstatic void main(String[] args) throws IOException { //写数据 //write(); read(); } privatestatic void read() throws IOException { //DataInputStream:读数据 //创建对象:publicDataInputStream(InputStream in) DataInputStreamdis = new DataInputStream(new FileInputStream("dos.txt")); //读数据了,按什么顺序写入就必须按照什么顺序读出来 System.out.println(dis.readByte()); System.out.println(dis.readShort()); System.out.println(dis.readInt()); System.out.println(dis.readLong()); System.out.println(dis.readChar()); System.out.println(dis.readFloat()); System.out.println(dis.readDouble()); System.out.println(dis.readBoolean()); //关流 dis.close(); } privatestatic void write() throws IOException { //publicDataOutputStream(OutputStream out) DataOutputStreamdos = new DataOutputStream(new FileOutputStream("dos.txt")); //给流关联的文件中写入基本类型的数据 dos.writeByte(20); dos.writeShort(200); dos.writeInt(2000); dos.writeLong(20000L); dos.writeChar(97); dos.writeFloat(12.34F); dos.writeDouble(23.34); dos.writeBoolean(true); //关流 dos.close(); } } 3. 内存操作流:解决临时数据存储的问题。 操作字节数组(演示着一个案例即可) ByteArrayInputStream ByteArrayOutputStream byte[] toByteArray() 将之前写入内存的流转换成字节数组 操作字符数组 CharArrayReader CharArrayWrite 操作字符串 StringReader StringWriter 案例:演示 操作字节数组 ByteArrayInputStream ByteArrayOutputStream 将数据写到流中保存在内存,并且读取 packagecom.edu_03; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * 操作字节数组(演示着一个案例即可) ByteArrayInputStream ByteArrayOutputStream byte[] toByteArray() 将之前写入内存的流转换成字节数组 * */ public class ByteArrayOutputStreamDemo { publicstatic void main(String[] args) throws IOException { //给内存中写数据publicByteArrayOutputStream() ByteArrayOutputStreambaos = new ByteArrayOutputStream(); //给内存中调用方法写数据 baos.write("hello".getBytes()); //将写入内存中的数据读取出来 byte[]buf = baos.toByteArray();//调用这个方法,将之前写入内存中的数据存储到字节数组中 ByteArrayInputStreambais = new ByteArrayInputStream(buf);//将刚才存储到字节数组中的内容关联上bais //只有这样之后,我们才可以直接从bais中读取我们想要的内容 //一次读取一个字节 intby; while((by=bais.read())!=-1) { System.out.print((char)by); } //关流 bais.close(); baos.close(); } } 4. * 打印流: * 字节打印流 PrintStream * 字符打印流 PrintWriter * * 特点: * A:只能操作目的地,不能操作数据源 * B:可以操作任意类型的数据 * C:如果启动了自动刷新,能够自动刷新 * D:可以操作文件的流 * 注意:什么流可以直接操作文件? 看流对象的API,如果其构造方法同时有File和String类型的参数,就可以直接操作文件。 案例1:利用字符打印流给文件中书写数据(String类型),需要手动刷新 package com.edu_04; import java.io.IOException; import java.io.PrintWriter; /** * 4. * 打印流: * 字节打印流 PrintStream * 字符打印流 PrintWriter * * 特点: * A:只能操作目的地,不能操作数据源 * B:可以操作任意类型的数据 * C:如果启动了自动刷新,能够自动刷新 * D:可以操作文件的流 * 注意:什么流可以直接操作文件? 看流对象的API,如果其构造方法同时有File和String类型的参数,就可以直接操作文件。 * */ public class PrintWriterDemo { publicstatic void main(String[] args) throws IOException { //使用打印流给文件中写入hello,java,world //publicPrintWriter(String fileName) PrintWriterpw = new PrintWriter("pw.txt"); //给流关联的文件中写数据 pw.write("hello"); pw.write("java"); pw.write("world"); //刷新 pw.flush(); //3.关流 pw.close(); } } * 操作任意类型的数据呢? *print() *println():如果启动了自动刷新,能够实现刷新,而且还实现了自动换行。 * 如何启动自动刷新:利用构造 *PrintWriter(OutputStream out, boolean autoFlush) *PrintWriter(Writer out, boolean autoFlush) * * 如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作 案例3:利用字符打印流复制java文件(BufferedReader+PrintWriter) package com.edu_04; import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; public class PrintWriterDemo3 { publicstatic void main(String[] args) throws IOException { /** * 案例3:利用字符打印流复制java文件(BufferedReader+PrintWriter) */ //数据源 BufferedReaderbr = new BufferedReader(new FileReader("PrintWriterDemo.java")); //目的地 //PrintWriter(Writerout, boolean autoFlush) PrintWriterpw = new PrintWriter(new FileWriter("copy.java"),true); //读一行写一行 Stringline; while((line=br.readLine())!=null) { pw.println(line);//1.写数据 2.换行 3.刷新 } //关流 pw.close(); br.close(); } } 5.标准输入输出流 *System类下有这样的两个成员变量: * 标准输入流: * public static final InputStream in 案例1:利用标注输入流进行键盘录入,录入后读取流并打印在控制台 packagecom.edu_05; import java.io.IOException; import java.io.InputStream; public class SystemIn { publicstatic void main(String[] args) throws IOException { /** * public static final InputStream in */ //将键盘录入的数据封装在了输入流中 //Scannersc = new Scanner(System.in); InputStreamis = System.in; //将键盘录入的数据从输入流中读取出来 intby; while((by=is.read())!=-1) { System.out.print((char)by); } //关流 is.close(); } } 案例2:用IO流实现键盘录入,一次读取一行数据 分析: InputStream is = System.in; BufferedReader是字符缓冲流,是对字符流进行高效操作的 所以,参数必须是字符类型 而我们现在有的是字节类型的流 请问:怎么办呢?转换流 packagecom.edu_05; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class SystemIn2 { publicstatic void main(String[] args) throws IOException { /** * 案例2:用IO流实现键盘录入,一次读取一行数据 * InputStream is = System.in; * InputSreamReader isr = newInputStreamReader(is) * BufferedReader br = new BufferedReader(isr); */ //将上面的分析写为一部 BufferedReaderbr = new BufferedReader(new InputStreamReader(System.in)); //一次读取一行数据 System.out.println("请输入你的姓名"); Stringname = br.readLine(); System.out.println("请输入你的年龄"); Stringage = br.readLine(); System.out.println(name+":"+age); } } * 标准输出流: * public static final PrintStream out 案例:解析输出语句System.out.println("helloworld"); packagecom.edu_05; import java.io.PrintStream; /** * 标准输出流: * public static final PrintStream out 案例:解析输出语句System.out.println("helloworld"); * */ public class SystemOut { publicstatic void main(String[] args) { // PrintStreamps = System.out; // ps.println(true); //上面两行合并为一行,底层调用的字节打印流中的方法 System.out.println(true); } } 6. * 合并流:SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。 构造: SequenceInputStream(InputStream s1, InputStream s2) :将s1和s2合并成一个输入流,先读取s1后读取s2 * * 案例1: * 我要把DataStreamDemo.java和ByteArrayStreamDemo.java写到一个文件Copy.java * * 数据源: * DataStreamDemo.java * ByteArrayStreamDemo.java * 目的地: * Copy.java packagecom.edu_06; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.SequenceInputStream; /** * 6. * 合并流:SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。 构造: SequenceInputStream(InputStream s1, InputStream s2) :将s1和s2合并成一个输入流,先读取s1后读取s2 * * 案例1: * 我要把DataStreamDemo.java和ByteArrayStreamDemo.java写到一个文件Copy.java * * 数据源: * DataStreamDemo.java * ByteArrayStreamDemo.java * 目的地: * Copy.java * */ public class SequenceInputStreamDemo { publicstatic void main(String[] args) throws IOException { //创建合并流对象 //SequenceInputStream(InputStreams1, InputStream s2) :将s1和s2合并成一个输入流,先读取s1后读取s2 //将两个数据源合而为一 SequenceInputStreamsis = new SequenceInputStream(newFileInputStream("PrintWriterDemo.java"), newFileInputStream("SystemIn2.java")); //封装目的地 FileOutputStreamfos = new FileOutputStream("copy2.java"); //一下读写一个字节数组 byte[]buf = new byte[1024]; intlen; while((len=sis.read(buf))!=-1) { //读多少写多少 fos.write(buf,0, len); } //关流 fos.close(); sis.close(); } } 8. 对象的序列化和反序列化 * 序列化流:把对象按照流一样的方式写到文件或者在网络中传输。 * 反序列化流:把文件或者网络中的流对象数据还原对象。 * *ObjectOutputStream:序列化流 writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。 *ObjectInputStream:反序列化流 Object readObject() 从 ObjectInputStream 读取对象。 * 注意:如果一个类不是实现Serializable接口无法把实例化,会报异常java.io.NotSerializableException * 类通过实现java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。 * * 如何实现序列化? * 让对象所属类的实现序列化接口。 9. Properties(查看api实现map接口本质是一个map集合) 9.1 *Properties:Properties 类表示了一个持久的属性集。属性列表中每个键及其对应值都是一个字符串。 * 特点:Properties可保存在流中或从流中加载。 案例:使用map集合的put方法给集合中存储数据并且遍历 9.2 *Properties的特有功能: * A:添加元素 * public ObjectsetProperty(String key,String value) * B:获取元素 * public StringgetProperty(String key) * public Set<String>stringPropertyNames() 案例:使用它的特有功能添加元素并遍历 packagecom.edu_08; import java.util.Properties; import java.util.Set; /** * 9.2 *Properties的特有功能: * A:添加元素 * public ObjectsetProperty(String key,String value) * B:获取元素 * public StringgetProperty(String key) * public Set<String>stringPropertyNames() 案例:使用它的特有功能添加元素并遍历 * */ public class PropertiesDemo2 { publicstatic void main(String[] args) { //创建Properties这个集合 Propertiesprop = new Properties(); //调用publicObject setProperty(String key,String value) prop.setProperty("huangxiaoming","baby"); prop.setProperty("dengchao","sunli"); prop.setProperty("xidada","pengliyuan"); //1.获取所有键的集合 //publicSet<String> stringPropertyNames() Set<String>keys = prop.stringPropertyNames(); //遍历键,根据键找值 for(String key : keys) { System.out.println(key+":"+prop.getProperty(key)); } } } 9.3 * 可以和IO流进行结合使用: * 把文件中的数据加载到集合中。注意:文件中的数据必须是键值对象形式的(例如:张杰=谢娜)。 * public void load(InputStreaminStream) * public void load(Reader reader) 案例:创建一个键值对文件,将文件中的键值对加载到集合中,输出集合 packagecom.edu_08; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.Properties; import java.util.Set; /** * 可以和IO流进行结合使用: * 把文件中的数据加载到集合中。注意:文件中的数据必须是键值对象形式的(例如:张杰=谢娜)。 * public void load(InputStreaminStream) * public void load(Reader reader) 案例:创建一个键值对文件,将文件中的键值对加载到集合中,输出集合 * */ public class PropertiesDemo3 { publicstatic void main(String[] args) throws IOException { //创建集合 Propertiesprop = new Properties(); //将文件中的键值对,加载到集合中 prop.load(newFileReader("prop.txt")); //遍历集合 Set<String>keys = prop.stringPropertyNames(); for(String key : keys) { System.out.println(key+":"+prop.getProperty(key)); } } } * * 把集合中的数据存储到文本文件中,并且是按照键值对形式存储的。 * public void store(OutputStreamout,String comments) * public void store(Writerwriter,String comments) 案例:将创建的键值对集合加载到文件中 packagecom.edu_08; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; /** * 把集合中的数据存储到文本文件中,并且是按照键值对形式存储的。 * public void store(OutputStreamout,String comments) * public void store(Writerwriter,String comments) 案例:将创建的键值对集合加载到文件中 * */ public class PropertiesDemo4 { publicstatic void main(String[] args) throws IOException { //创建集合 Propertiesprop = new Properties(); //给集合中存储数据 prop.setProperty("liudehua","50"); prop.setProperty("liming","60"); prop.setProperty("zhangxueyou","40"); //将集合中的元素,存储到文本文件中 prop.store(newFileWriter("prop2.txt"), "name=age"); } } 案例:我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100” packagecom.edu_09; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; import java.util.Set; public class PropTest { publicstatic void main(String[] args) throws IOException { /** * 案例:我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100” zhangsan=3 lisi=4 wangwu=5 1.创建集合对象 2.将文件中的键值对加载到集合中 3.获取多有的键的集合,遍历,判断 4.如果存在lisi,的话,给集合中重新存储键值对lisi=100 5.将集合中的数据存储到文件中 */ //1.创建集合对象 Propertiesprop = new Properties(); //2.将文件中的键值对加载到集合中 prop.load(newFileReader("prop3.txt")); //3.获取多有的键的集合,遍历,判断 Set<String>keys = prop.stringPropertyNames(); //4.如果存在lisi,的话,给集合中重新存储键值对lisi=100 for(String key : keys) { if("lisi".equals(key)) { prop.setProperty(key,"100"); } } //5.将集合中的数据存储到文件中 prop.store(newFileWriter("prop3.txt"), null); } } 案例:我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次, 超过5次提示:游戏试玩已结束,请付费。 package com.edu_01; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; /** * 案例:我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次, 超过5次提示:游戏试玩已结束,请付费。 * 1.将文件中的键值对加载到集合中 * 2.拿出已经玩耍的次数做判断 * 3.如果已经超过5次,提示付费 * 4.如果少于5次开启游戏,将文件中的次数+1 */ public class PropTest { publicstatic void main(String[] args) throws IOException { //1.将文件中的键值对加载到集合中 Propertiesprop = new Properties(); prop.load(newFileReader("count.txt")); //2.拿出已经玩耍的次数做判断 Stringcount = prop.getProperty("count"); //将String类型转换为int类型 intnumber = Integer.parseInt(count); if(number>4) { System.out.println("次数已到,请付费"); }else{ //开启游戏 GuessNumber.startGame(); number++; //将自增的次数重新存储到文件中 prop.setProperty("count",number+""); //将新的prop集合存储到文件中 prop.store(newFileWriter("count.txt"), null); } } } package com.edu_01; import java.util.Scanner; public class GuessNumber { publicstatic void startGame(){ intran = (int) (Math.random()*100+1); Scannersc = new Scanner(System.in); System.out.println("请输入你猜测得数字"); while(true) { intnumber = sc.nextInt(); if(number>ran) { System.out.println("大了"); }elseif (number<ran) { System.out.println("小了"); }elseif (number==ran) { System.out.println("猜对了"); break; } } } } 十五天: 1:多线程(理解) (1)线程是依赖于进程而存在的。 A:进程 正在运行的应用程序 B:线程 进程的执行路径,执行单元 案例:画图理解单线程和多线程的代码执行流程 (2)多线程的两种方案:(掌握) 请参照:多线程两种方式 继承Thread类(查看api简单介绍Thread类): 实现Runable接口: packagecom.edu_02; /** * 继承Thread类(查看api简单介绍Thread类): * */ public class MyThread extends Thread{ //1.继承Thread类 //2.重写run方法,重写run方法中的代码之后,当我们启动了这个线程之后,我们的这个线程就会执行run方法中的代码 @Override publicvoid run() { //需求:开启该线程之后,执行一个for循环 for(int i = 0; i < 10; i++) { System.out.println(i); } } } package com.edu_02; public class Test { publicstatic void main(String[] args) { //只要我们创建了一个线程对象,并且启动该线程的实例,我们就相当于开启了一个线程 MyThreadmt = new MyThread(); mt.start();//1.开启了一个线程 2.让开启的这个线程执行他对应的类中的run方法 //在次创建一个子线程,并开启这个子线程执行他的run方法 MyThreadmt2 = new MyThread(); mt2.start(); } } (3)多线程的几个问题: A:启动线程用的是哪个方法 start() B:start()和run()的区别 start():1.开启线程 2.执行run()方法里面的代码 run():执行的是线程里面执行的代码,并不会开启线程 C:为什么要重写run() 因为每个线程需要执行的代码都是都是不一样的, 我们需要将每个线程自己独立执行的代码写到run()方法中执行 D:线程可以多次启动吗 (4)线程的调度和控制 线程休眠(Thread.sleep(毫秒值)) 线程名称(setName(),getName();) 线程的调度及优先级setPriority(10)(注意默认值是5,区间在1-10之间) 什么叫线程优先级:说白了就是设置你抢占cpu执行权抢占到的概率 (5)多线程案例(两种方式实现,睡一会出现线程安全问题): 5.1继承Thread卖票 5.2实现Runnable卖票(睡一会出现线程安全问题) 问题: 按照真实的情景加入了延迟,确发现出现了这样的两个问题: A:相同的票卖了多次 CPU的一次操作必须是原子性的(操作是CPU执行一次就可以直接完成的) B:出现了负数的票 随机性和延迟导致的 出现上面的问题称为线程安全问题。 (6)多线程安全问题 A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 (7)如何解决多线程安全问题(掌握) *线程安全执行效率就低 A:同步代码块(测试不是同一个锁的情况,测试是同一个锁的情况) synchronized(对象) { 需要被同步的代码。 } 需求:1.测试不是同一把锁的时候线程安全吗? 2.如果是同一把锁线程安全吗? 两个问题:1.对象是什么 ? 答:任意对象 ,相当于是一把锁,只要线程进去就把锁锁上 2.需要同步的代码? 答:被线程执行的代码 C:锁对象问题 a:同步代码块(定义一个抽象类,里面专门定义一个锁) 任意对象 b:同步方法(仅适用于实现runable接口) publicsynchronized void sellTicket(){同步代码} this c:静态同步方法 类的字节码对象 publicstatic synchronized void sellTicket() { 需要同步的代码 } (8)匿名内部类的方式使用多线程(掌握) newThread() { publicvoid run() { ... } }.start(); newThread(new Runnable(){ publicvoid run() { ... } }).start(); 案例:利用匿名内部类,启动多个线程,验证单例设计模式之懒汉式所存在的缺陷, 当使用多线程来搞的时候就不单例了。。 (9)JDK5的Lock锁,我们之前造的所有的锁都没有手动释放锁 staticLock lock = new ReentrantLock(); 枷锁:lock.lock(); 释放锁:lock.unlock(); 可以让我们明确的知道在哪里加锁和释放锁。 依然写一个卖票的demo,用lock枷锁释放锁, 为了保证我们创建的锁一定会被释放,用一下代码进行改进 try{....}finally{.....} (10)死锁问题 同步嵌套,锁里面套了一个锁,出现同步嵌套 (简单介绍,要求大家以后写的时候需要注意) (11)线程等待和唤醒机制(案例演示:waitThread,NotifyThread,MyLock,Test) 锁对象调用wait()锁对象调用notify() 注意: wait和sleep的区别 线程等待,在等待的同时释放锁,而sleep()方法在执行的过程中是不会释放锁的
以上是关于十十五天笔记总结的主要内容,如果未能解决你的问题,请参考以下文章