目录
2. Java进阶
2.6?Java常用类
2.6.1 IO
2.6.1.1 定义
2.6.1.2?IO的分类
?2.6.2 File类
2.6.2.1 定义
2.6.2.2 File类的构造方法
2.6.2.3?文件属性
2.6.2.4?目录
2.6.2.5?列出指定类型的文件
2.6.3 Java Logger
2.6.3.1 创建Logger对象
2.6.3.3 Logger的Handler
2.6.3.4 Logger的Formatter
2.6.4 容器
2.6.4.1 定义
2.6.4.2 ArrayList
2.6.4.3 HashMap
2.6.5 多线程
2.6.5.1 定义
2.6.5.2 多线程实现
2.6.5.3 线程同步
2. Java进阶
2.6?Java常用类
2.6.1 IO
2.6.1.1 定义
Java核心库 java.io提供了全面的IO接口:文件读写,标准设备输出等。 Java IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。 ?? ??? ??? ???
2.6.1.2?IO的分类
1)根据处理的数据类型不同:字节流和字符流 字符流 Reader ?? ??? ?BufferedReader ?? ??? ?InputStreamReader ?? ??? ?FileReader Writer ?? ??? ??BufferedWriter ?? ??? ??OutputStreamWriter ?? ??? ??FileWriter 字节流 InputStream ?? ??? ???FileInputStream ?? ??? ???FilterInputStream ?? ??? ???BufferedInputStream OutputStream ?? ??? ??? FileOutputStream ?? ??? ??? ?FilterOutputStream ?? ??? ??? ?BufferedOutputStream
2)根据流向不同:输入流和输出流 字符流的由来 ?? ??? ??因为文件编码的不同,而有了对字符进行高效操作的字符流对象。 ?? ??? ???对象:基于字节流读取字节时,去查了指定的码表。 ?? ??? ??? ??? ?
3)字节流和字符流的区别 (1)字节流读取时,读到一个字节就返回一个字节。字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8码表中是3个字节)时,先去查指定的编码表,将查到的字符返回。 (2)字节流可以处理所有类型数据,如图片,MP3,AVI。而字符流只能处理字符数据。 结论:只要是处理纯文本数据,就优先考虑字符流,其他就用字节流。 ?? ??? ??? ??? ?
4)转换流 (1)是字节流和字符流之间的桥梁 (2)该流对象中可以对读取到字节数据进行指定编码表的编码转换 ?? ??? ??? ??? ??? ?
应用场景 (1)当字节和字符之间有转换动作时 (2)流操作的数据需要进行编码表的指定时 ?? ??? ??? ??? ??? ?
具体的对象体现 (1)InputStreamReader: 字节到字符的桥梁 (2)OutputStreamWriter: 字符到字节的桥梁
5)Reader和Writer常用方法 测试开发中涉及的IO操作,大多与日志相关,所以重点看关于Reader和Writer相关的常用API ?? ??? ??? ??? ??? ?
Reader InputStreamReader FileReader:专门用于处理文件的字符读取流对象。 ?? ??? ??? ??? ???
Writer ?OutputStreamWriter ?FileWriter:专门用于处理文件的字符写入流对象 ?? ??? ??? ??? ?
Reader中的常用方法 (1)int read():读取一个字符,返回的是读到的那个字符。如果读到流的末尾,返回-1 ?(2)int read(char[]):将读到的字符存入指定的数组中,返回的是读到的字符个数,即往数组里装的元素个数。如果读到末尾,返回-1 (3)close():读取字符后,进行资源释放 ?? ??? ??? ??? ?
Writer中的常用方法 (1)writer(int c):将一个字符写入到流中 (2)writer(char []):将一个字符数组写入到流中 (3)writer(String):将一个字符串写入到流中
(4)flush(): 刷新流,将流中的数据刷新到新的目的地中,流还在 ?(5)close():关闭资源,在关闭钱会先调用flush(),刷新流中的数据去目的地,然后关闭流 ?? ??? ??? ??? ?
FileWriter(String filename) ? ? ? 1)调用系统资源 ? ? ? 2)在指定位置,创建一个文件。如果文件已经存在,将会被覆盖 ? ? ? ? ? ?FileWriter(String filename, boolean append) ? ? ? ? ? ?当boolean为true时,会在指定文件末尾处进行数据的续写。 ?? ??? ??? ??? ?
FileReader(String filename) (1)用于读取文本文件的流对象 (2)用于关联文本文件 (3)综合应用(高级) ?? 流操作的基本规律 ?? ??? ??? 明确数据源和数据汇(数据目的)。为了明确输入流还是输出流 ?? ??? ??? ?明确操作的数据是否是纯文本数据。为了明确字符流还是字节流 ?? ??? ??? ??? ?
【常见码表】 ASCII:美国标准信息交换码。使用的是1个字节的7位来表示该表中的字符 ISO 8859-1:拉丁码表。使用一个字节来表示 GB2312:简体中文码表 GBK:简体中文码表,比GB2312融入更多的中文文件和符号 Unicode:国际标准码表。都用两个字节表示一个字符 UTF-8:对unicode进行优化,每一个字节都加入标识头
实例需求 ?? ??? ??将键盘录入的数据存储到一个文件中 数据源 ?? ??? ???System.in 输入流,包括InputStream, Reader ?? ??? ???因为键盘录入一定是纯文本数据,所以选择Reader ?? ??? ?? 因为System.in对应的是字节读取流,因此要进行转换,将字节转换成字符,所以选择InputStreamReader ?? ??? ??? 如果要提高效率,则加入字符流的缓冲区BufferedReader ?? ??? ??? BufferedReader ?bur=new BufferedReader(new InputStreamReader(System.in)) ?? ??? ??? ??? ?
数据汇 ?? ??? ??? ?一个文件,硬盘。输出流,包括outputStream writer ?? ??? ??? 因为要往文件存储的都是文本数据,所以选择writer ?? ??? ??? 因为操作的是一个文件,所以选择FileWriter ?? ??? ??? 如果要提高效率,则使用BufferedWriter ?? ??? ??? ?Buffered bufr=new BufferedWriter(new FileWriter("a.txt")) 附加需求 ?? ??? ??"将文本数据按照执行的编码表存入文件中" ?? ??? ???因为往文件存储的都是文本数据,所以选writer ?? ??? ??? 因为要指定编码表,所以要用writer中的转换流,outputStreamWriter ?? ??? ??? 如果要提高效率,选择BufferedWriter(最终是文件,但不能选择FileWriter, 使用默认编码) 输出转换流要接收一个字节输出流进来,所以要使用outputStream体系,最终输出到一个文件中,那么就需要使用OutputStream体系中可以操作文件的字节流对象。
?? ??? ??? ??? ??? ??? 2.6.2 File类
2.6.2.1 定义
File类的对象,主要用来获取文件本身的一些信息,比如文件所在目录,文件长度,文件读写权限等,不涉及对文件的读写操作 ?? ??? ??? ?
2.6.2.2 File类的构造方法
File(String filename) File(String directoryPath, String filename) File(file f, String filename)
2.6.2.3?文件属性
public String getName():获取文件的名字 public boolean canRead():判断文件是否可读 public boolean canWrite():判断文件是否可写 public boolean exits():判断文件是否存在 public long length():获取文件长度 public String getAbsolutePath():获取文件的绝对路径 public String getParent():获取文件的父目录 public boolean isFile():判断文件是否是一个正常文件而不是目录 public boolean isDirectory():判断文件是否一个目录 public boolean isHidden():判断文件是否是隐藏文件 public long lastModified():文件最后修改的时间(1990年五月至文件最后修改时刻的毫秒数)
2.6.2.4?目录
创建目录: public boolean mkdir() 如果File对象是一个目录,那么该对象可以调用下述方法列出该目录下的文件和子目录 public String[] list():用字符串形式返回 public File[] listFiles:用File对象形式返回
2.6.2.5?列出指定类型的文件
public String[] list(FilenameFilter obj):字符串形式目录下指定类型的所有数据
public File[] listFiles(FilenameFilter obj):用File对象形式返回目录下指定类型的所有文件。其中,FilenameFilter是一个接口,该接口有一个方法
public boolean accept(File dir, String name):当想list方法传递一个实现该接口的对象时,dir调用list方法在列出文件时,将调用accept方法检查该文件Name是否符合accept方法指定的目录和文件名字要求
2.6.3 Java Logger
2.6.3.1 创建Logger对象
static Logger getLogger(String name):为指定子系统查找或创建一个logger static Logger getLogger(String name, String resourceBundleName):?为指定子系统查找或创建一个logger ?注意:name是Logger的名称,当名称相同时,同一个名称的Logger只能创建一个
2.6.3.2 Logger的级别
全部定义在java.util.logging.Level里面 级别降序 ?? ??? ??? ??? ??? ?SEVERE(最高值) ?? ??? ??? ??? ??? ?WARNING ?? ??? ??? ??? ??? ?INFO ?? ??? ??? ??? ??? ?CONFIG ?? ??? ??? ??? ??? ?FINE ?? ??? ??? ??? ??? ?FINER ?? ??? ??? ??? ??? ?FINEST(最低值) ?还有一个级别OFF, 用来关闭日志记录,使用几杯ALL启用所有消息的日志记录。 ?默认级别INFO, 比INFO低的日志不显示 ?默认级别定义在jre安装目录的lib下面的logging.propertities文件中。 logger的命名 一般使用圆点分隔的层次命名空间来命名Logger
2.6.3.3 Logger的Handler
Handler对象从Logger中获取日志信息,并将这些信息导出。 可以通过执行setLevel(Level.OFF)来禁用Handler,并可通过执行适当级别的setLevel来重新启用 Handler类通常使用LogManager属性来设置Handler的Filter, Formatter和Level的默认值 ?? ??? ??? ??? ??? ?java.util.logging.Handler ?? ??? ??? ??? ??? ?java.util.logging.MemoryHandler ?? ??? ??? ??? ??? ?java.util.logging.StreamHandler ?? ??? ??? ??? ??? ?java.util.logging.ConsoleHandler ?? ??? ??? ??? ??? ?java.util.logging.FileHandler ?? ??? ??? ??? ??? ?java.util.logging.SocketHandler ?注意:默认的日志方式是XML格式。如果想要自定义logger的格式,需要用Formatter来定义。
Formatter为格式化LogRecords提供支持 ?一般每个日志记录Handler都有关联的Formatter. Formatter接受LogRecord, 并将它转换为一个字符串。 有些formatter(如XML Formatter)需要围绕一组格式化记录来包装头部和尾部字符串。可以使用getHeader和getTail方法来获得这些字符串。 ?LogRecord对象用于在日志框架和单个日志Handler之间传递日志请求 ?LogRecord(Level level, String msg) ? 用给定级别和消息值构造LogRecord ?? ??? ??? ??? ??? ?java.util,logging,Formatter ?? ??? ??? ??? ??? ?java.util,logging,SimpleFormat ?? ??? ??? ??? ??? ?java.util,logging,XMLFormatter
2.6.4 容器
2.6.4.1 定义
Java中的容器提供了完善的方法来保存对象,可以使用这些工具来解决大数量的问题。 分类;图略 解释:数据容器主要分为两类 Collection:存放独立元素的序列 Map:存放key-value型的元素对 ?? ??? ??? ??? ?
最常用的四个容器: LinkedList:其数据结构采用的是链表,此种结构的优势是删除和添加的效率很高,但随机访问元素是效率较ArrayList低
ArrayList:其数据结构采用的是线性表,此种结构的优势是访问和查询十分方便,但添加和删除的效率低
HashSet:Set类不允许其中存在重复的元素(集),无法添加一个重复的元素。HashSet利用Hash函数进行了查询效率上的优化,其contain()方法经常被使用,以用于判断相关元素是否被添加过 ?
HashMap:提供了key-value的键值对数据存储机制,可以十分方便的通过键值查找相应的元素,而且通过Hash三列机智,查找十分方便
2.6.4.2 ArrayList
(1)定义: ArrayList就是动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了这些好处: 动态的增加和减少元素 实现了ICollection和IList接口 灵活的设置数组的大小 ?? ??? ??? ??? ?
(2)动态数组扩容 ArrayList底层采用Object类型的数组实现,当使用不带参数的构造方法生成ArrayList对象时,会在底层生成一个长度为10的Object类型数组 200个数据动态加到上面数组,会5次扩容:10*2*2*2*2*2=320才会满足。如果一开始就定义 ArrayList List= new ArrayList(210)创建ArrayList,则不用扩容和Copy,减少内存使用 ?? ??? ??? ??? ?
(3)常用方法 声明 ArrayList list = new ArrayList(); 给数组增加5个元素 ?for(int i=0; i<5; i++) ?list.add(i); ArrayList转换为String ?System.out.print(list.toString()); 删除第3个值 ?list.remove(2) 在第三个位置插入2 list.add(2,2) 再增加10个元素 for(int i=0; i<10; i++) ? ? list.add(i+10); ArrayList转换为Array Object[] obj = list.toArray(); for(Objuect i: obj){ ? ? System.out.print(i); }
2.6.4.3 HashMap
(1)定义 Map中我们通过对象来对对象进行索引,用来索引的对象叫做key, 其对应的对象叫做value。 HashMap是一个散列表,它存储的内容是键值对key-value映射 ?? ??? ??? ??? ?
(2)常用方法 ?? ??? ??? ??? ??? ?HashMap存储 ?? ??? ??? ??? ??? ?HashMap hm=new HshMap(); ????????????????????hm.put("a","test1"); ? ? ? ? ? ? ? ? ? ??hm.put("b", "test2"); ? ? ? ? ? ? ? ? ? ??hm.put("c", "test3"); ?? ??? ??? ??? ??? ?测试是否包含关键字"a" ?? ??? ??? ??? ??? ??? ?System.out.print(hm.containsKey("a")); ?? ??? ??? ??? ??? ?测试是否包含关键字“b” ?? ??? ??? ??? ??? ??? ?System.out.print(hm.containsKey("b")); ?? ??? ??? ??? ??? ?取得关键字“a”的value ?? ??? ??? ??? ??? ??? ?System.out.print(hm.get("a")); ????????????????????????System.out.print(hm.entrySet()); ?? ??? ??? ??? ??? ?HashMap遍历 ?? ??? ??? ??? ??? ??? ?Iterator it=hm.entrySet().iterator(); ? ? ? ? ? ? ? ? ? ??while(it.hasNext()){ ? ? ????????????????????????System.out.println(it.next()); ? ? ? ? ? ? ? ? ? ?} ?? ??? ??? ??? ??? ?keySet()返回关键字的集合 ?? ??? ??? ??? ??? ??? ?it.hm.keySet().iterator(); ? ? ? ? ? ? ? ? ? ??while(it.hasNext()){ ? ? ????????????????????????System.out.print(it.next()); ? ? ? ? ? ? ? ? ? ??} ?? ??? ??? ??? ??? ?values()放回值的集合 ?? ??? ??? ??? ??? ??? ?it=hm.values().iterator(); ? ? ? ? ? ? ? ? ? ??while(it.hasNext()){ ? ????????????????????????? System.out.print(it.next()); ? ? ? ? ? ? ? ? ? ??} ?? ??? ??? ??? ??? ?删除key c 以及其对应的value ?? ??? ??? ??? ??? ??? ?hm.remove("c") ?? ??? ??? ??? ??? ?删除key c后进行hashmap遍历 ?? ??? ??? ??? ??? ??? ?接上
? ? ? ? ? ? ? ? ? ? it=hm.entrySet().iterator(); ? ? ? ? ? ? ? ? ? ??while(it.hasNext()){ ? ? ????????????????????????System.out.print(it.next()); ? ? ? ? ? ? ? ? ? ??}
2.6.5 多线程
2.6.5.1 定义
1)简言之,一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,多线程程序的并发性高。另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而提高了程序的运行效率。
2)线程的一定条件下,状态会发生变化。
3)线程的几个状态
新建状态 New:新创建一个线程对象
就绪状态 Runnable:线程对象创建后,其他线程调用了该对象的start方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
运行状态 Running:就绪状态的线程获取了CPU,执行程序代码。
阻塞状态 Blocked:是线程因为某种原因放弃CPU使用权,暂时停止运行,直到线程进入就绪状态,才有机会转到运行状态。
---等待阻塞:运行的线程执行wati()方法,JVM会把该线程放入等待池中。
---同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
---其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程设置为阻塞状态。当sleep()状态超时,join()等待线程终止或超时,或者I/O处理完毕,线程重新转入就绪状态。
死亡状态 Dead:线程执行完了或者因一场退出了run()方法,该线程结束生命周期。
2.6.5.2 多线程实现
Java要实现多线程,有两种手段:
1)继承Thread类??
2)实现Runable接口
1)对于直接继承Thread的类来说
代码框架:
class MyThread1 extends Thread{
??? public void run(){
??????? try{
??????????? Thread.sleep(200);
??????? }catch(InterrupteException e){
??????????? e.printStackTrace();
??????? }
??????? for(int i=0; i<7; i++){
??????????? if(count>0){
?????????? System.out.print(Thread.currentThread().getName()+": count"+count--);
???????????? }
??????? }
??? }
??? public static void main(String[] args){
??????? MyThread1 h1 = new MyThread1();
??????? MyThread1 h2 = new MyThread1();
??????? MyThread1 h3 = new MyThread1();
??????? h1.start();
??????? h2.start();
??????? h3.start();
??? }
??? private int count=5;
}
缺点:
Java不支持多继承
不利于资源共享
2)实现Runable接口
代码框架:
class MyThread2 implements Runable {
??? private int count =5;
??? public void run(){
??????? try{
??????????? Thread.sleep(200);
??????? }catch(InterrupteException e){
??????????? e.printStackTrace();
??????? }
??????? for(int i=0; i<7; i++){
??????????? if(count>0){
?????????? System.out.print(Thread.currentThread().getName()+": count"+count--);
???????????? }
??????? }
??? }
??? public static void main(String[] args){
??????? MyThread2 my = new MyThread2();
??????? new Thread(my,"Thread 1").start();
??????? new Thread(my,"Thread 2").start();
??????? new Thread(my,"Thread 3").start();
??? }
}
2.6.5.3 线程同步
1)定义
多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步泳衣解决多个线程同时访问可能出现的问题。同步机制可以使用synchronized关键字实现。
2)syschronized方法
当synchronized关键字修饰一个方法时,该方法叫做同步方法。
当synchronized方法执行完或发生异常时,会自动释放锁。
Java中的每个对象都有一个锁lock, 或者叫做监视器monitor,当一个线程访问某个对象的synchronized方法时,将该对象上锁,其他任何线程都无法再去访问该对象的synchronized方法了 (这里指所有的同步方法,而不仅仅是同一个方法),直到之前的那个线程执行方法完毕后(或者抛出异常),才将改对象的锁释放掉。其他线程才有可能再去访问该对象的synchronized方法。
注意,上面是给对象上锁,如果是不同的对象,那么各个对象之间没有限制关系。
??????????????????
3)synchronized块
写法:
synchronized(object){
}
表示线程在执行的时候,会将object对象上锁。注意这个对象可以是任意类的对象,也可以使用this关键字。这样就可以自行规定上锁对象。
|