day07
线程池:一个容纳多个线程的容器
应用: 其中的线程可以反复使用,省去了频繁创建线程对象的操作,
无需反复创建线程而消耗过多资源
线程池的工作原理:其中的线程可以反复使用,省去了频繁创建线程对象的操作, 无需反复创建线程而消耗过多资源
线程池的创建和使用步骤:
使用Executors的静态方法 newFixedThreadPool(int nThreads) 创建线程池ExecutorService
创建一个任务类, 实现Runnable接口, 重写run()方法
调用ExecutorService对象的 submit(Runnable task) 方法, 传递任务给线程池, 执行任务
调用ExecutorService对象的 shutdown() 方法, 销毁线程池 (不建议执行)
面向对象与函数式区别
面向对象: 强调"用哪个对象的哪个方法"来做事 (注重语法形式)
函数式: 强调做事 (不关心用什么对象, 重写什么方法)
JDK 8 中加入的Lambda表达式, 是函数式编程思想中的重点
Lambda表达式的3个部分:
1. 一些参数 ()
接口中抽象方法的参数列表. 没参数就空着; 有参数就写, 多个参数用逗号分隔
2. 一个箭头 ->
将参数传递给方法体
3. 一段代码 {}
重写接口抽象方法的方法体
Lambda省略原则:可推导的都可省略
使用前提:1. Lambda只能用于接口, 且"接口中有且仅有一个抽象方法"(也称为"函数式接口")
普通类, 抽象类不能用
2. 使用Lambda必须具有上下文推断
方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例
(简而言之: 作为参数类型的接口, 必须是函数式接口)
day08
Java.io.File类: 文件和目录的路径名的抽象表现形式,
主要用于文件和目录的创建, 查找和删除等操作
绝对路径:以盘符开始的路径
相对路径: 不以盘符开始的简化路径. 相对于项目的根目录
注意事项:
1. 路径不区分大小写 (在Windows系统中不区分大小写, Linux, Mac区分)
2. 路径一般写成字符串, 而字符串中一个\是转义, 所以要写两个\\
构造方法(创建了File对象, 并将其指向该路径. 不会真正在磁盘上创建这个文件)
File File(String pathname): 根据 路径字符串 封装一个File对象
File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
常用获取方法
String getAbsolutePath(): 返回此File的绝对路径名字符串
String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String getName(): 获取File对象的文件名或目录名
long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
常用判断方法
boolean exists(): 判断File对象代表的文件或目录是否实际存在
boolean isDirectory(): 判断File表示的是否为目录
boolean isFile(): 判断File表示的是否为文件
常用创建删除方法
boolean createNewFile(): 当文件不存在时, 创建一个新的空文件
boolean delete(): 删除由此File表示的文件或目录. (删除目录时必须是空目录)
boolean mkdir(): 创建File表示的目录
boolean mkdirs(): 创建File表示的多级目录
常用获取目录中内容的方法
String[] list(): 获取当前File目录下的所有子文件或目录的名字数组
File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组
注意:
只能用表示目录的File对象调用
用文件的File对象, 或者路径不存在, 调用会报错
递归思想:
遇到一个问题时, 将该问题拆解成可以解决的小问题, 如果解决不了, 继续拆解为更小的问题.
如果小问题解决了, 大问题也就能够解决
Java中实现递归的方式:
方法内部调用方法自己
递归的分类:
直接递归: 方法自己调用方法
间接递归: A方法调用B方法, B方法调用C方法, C方法调用A方法
递归时的注意事项:
1. 递归要有限定条件(出口), 保证递归能够停止(就是在某种情况下方法不再调用自己), 否则会栈内存溢出
2. 递归次数不能太多, 否则会栈内存溢出
3. 构造方法不能递归
递归的使用前提:
调用方法时, 方法的主体不变, 但每次传递的参数值不同, 可以使用递归
Filter过滤器
File[] listFiles(FileFilter filter): 通过File对象过滤, 返回文件过滤器过滤后的File对象数组
File[] listFiles(FilenameFilter filter): 通过File对象的文件名过滤, 返回文件过滤器过滤后的File对象数组
FileFilter接口: 用于File对象的过滤器
boolean accept(File pathName): true则会将参数的File对象加入返回的File[], false则不加入
FilenameFilter接口:
boolean accept(File dir, String name): true则会将参数的File对象加入返回的File[], false则不加入
day09
IO流IO的概念和分类IO流: 输入(Input)输出(Output)流
流: 数据流
以程序为中心
输入: 从硬盘(文件)读取到内存(Java程序)
输出: 从内存(Java程序)写入到硬盘(文件)
分类:
字节流 (读写字节: byte, 可以读写所有类型的文件, 包括视频, 图片, 音频, 文本等)
字节输入流: InputStream 抽象类
字节输出流: OutputStream 抽象类
字符流 (读写字符: String, 只能读写文本文件)
字符输入流: Reader 抽象类
字符输出流: Writer 抽象类
.OutputStream抽象类: 字节输出流 (顶层类)
成员方法
void close() :释放资源
void flush() :刷新缓冲区(对于字节流来说没有作用)
写字节的成员方法
abstract void write(int b): 一次写一个字节 (参数int便于传递byte的整数不用强转)
void write(byte[] b): 一次写一个字节数组
void write(byte[] b, int offset, int len): 一次写一个字节数组的一部分
FileOutputStream类: 文件字节输出流 (向文件写数据)
构造方法
FileOutputStream(String name): 通过文件路径创建文件字节输出流
FileOutputStream(File file): 通过File对象创建文件字节输出流
构造方法的作用:
创建一个FileOutputStream对象
根据构造方法传递的路径, 在磁盘上创建一个空文件 ("如果文件存在则会清空数据")
将创建的FileOutputStream对象指向这个磁盘上的文件
写数据的原理:
Java程序 -> JVM虚拟机 -> OS操作系统 -> OS调用写数据的方法 -> 将数据写入文件
使用字节输出流写数据到文件的步骤:
创建对象: 创建FileOutputStream对象, 构造方法中传递文件路径
写入数据: 使用FileOutputStream对象调用 write(int b) 方法, 将字节写入文件
释放资源: 使用FileOutputStream对象调用 close() 方法, 关闭流对象释放资源
Windows简体中文系统的程序打开是按 GBK 码表
IDEA中使用的是 UTF-8 码表
字节输出流: 续写
FileOutputStream(String name, boolean append): 通过文件路径创建流, true可以续写
FileOutputStream(File file, boolean append): 通过File对象创建流, true可以续写
换行符:
Windows系统: "\r\n"
Linux系统: "\n"
MacOS系统: "\r"
InputStream抽象类: 字节输入流 (顶层类)
常用成员方法
void close(): 释放资源
读数据的方法
int read(): 一次读一个字节
读到文件末尾返回-1 (返回int也是为了代码编写方便)
int read(byte[] b): 一次读一个字节数组
读到的字节存放在参数中的字节数组中, 返回int值是本次读到的字节的个数. 读到文件末尾返回-1
FileInputStream读数据步骤:
1. 创建FileInputStream对象
2. 使用FileInputStream对象, 调用 int read() 方法, 一次读取一个byte
3. 释放资源
GBK编码中, 一个汉字占用2个byte
UTF-8编码中, 一个汉字占用3个byte
字符流字符输入流: Reader和FileReader
注意: 字符流只能读写"文本文件"
Reader抽象类: 字符输入流 (顶层)
常用成员方法
void close() :关闭此流并释放与此流相关联的任何系统资源
读
int read(): 一次读一个字符char, 返回读到的字符.
读到文件末尾返回-1 (返回int为了代码编写方便)
int read(char[] cbuf): 一次读取一个字符数组char[]
返回读取的字符个数. 读到文件末尾返回-1
ileReader类: 文件字符输入流
构造方法
FileReader(File file): 根据File对象创建文件字符输入流
FileReader(String fileName): 根据File对象创建文件字符输入流
构造方法的作用:
1. 创建FileReader对象
2. 将FileReader对象指向磁盘上的文件
Reader抽象类: 字符输入流 (顶层)
int read(): 一次读一个字符char, 返回读到的字符.
读到文件末尾返回-1 (返回int为了代码编写方便)
int read(char[] cbuf): 一次读取一个字符数组char[]
返回读取的字符个数. 读到文件末尾返回-1
Java.lang.String类:
String(char[] value): 将char数组转换为String
String(char[] value, int offset, int count): 将char数组的一部分转换为String
Writer抽象类: 字符输出流 (顶层类) 'a''b' 缓冲区 97 98
常用成员方法
abstract void close(): 刷新缓冲区并释放资源
abstract void flush() :刷新缓冲区
写
void write(int c): 写一个字符 (int类型为了代码编写方便)
void write(char[] cbuf): 写一个字符数组
abstract void write(char[] b, int off, int len): 写一个字符数组的一部分
void write(String str): 写一个字符串
void write(String str, int off, int len): 写一个字符串的一部分
注意: write()方法只是将数据写到内存缓冲区, 最后必须调用flush()或close()才能将数据真正写入磁盘
.FileWriter类: 文件字符输出流
构造方法
FileWriter(File file): 通过File对象创建文件字符输出流
FileWriter(String fileName): 通过文件路径创建文件字符输出流
作用:
1. 创建FileWriter对象
2. 根据构造方法中的路径, 在磁盘上创建文件 ("如果文件已存在, 则清空文件内容")
3. 将FileWriter对象指向磁盘上的文件
字符输出流: 一次写一个字符
void write(int c): 写一个字符 (int类型为了代码编写方便)
FileWriter使用步骤:
1.创建FileWriter对象, 构造方法中绑定要写入数据的目的地
2.使用FileWriter中的方法 write(), 把数据写入到"内存缓冲区"中(字符转换为字节的过程)
3.使用FileWriter中的方法 flush(), 把内存缓冲区中的数据,"刷新到文件中"
4.释放资源 close() (会先把内存缓冲区中的数据刷新到文件中)
fush(): 刷新缓冲区 (将数据从内存中写入到磁盘)
close(): 刷新缓冲区, 并释放资源. 关闭流后不能再用同一个流对象操作
flush()可以省略, 只用close()来刷新并释放资源
写的其他方法:
void write(char[] cbuf): 写一个字符数组
abstract void write(char[] b, int off, int len): 写一个字符数组的一部分
void write(String str): 写一个字符串
void write(String str, int off, int len): 写一个字符串的一部分
字符输出流: 续写, 换行
FileWriter中带有续写功能的构造:
FileWriter(File file, boolean append): 通过File对象创建流. 第二个参数为true可以续写
FileWriter(String fileName, boolean append): 通过文件路径创建流. 第二个参数为true可以续写
换行:
windows: "\r\n" fw.write("\r\n");
补充:
字节流 和 字符流 如何选择:
1. 如果不确定读写的是什么类型的数据, 用字节流最通用
2. 如果确定读写的就是文本, 用字符流最方便
Properties双列集合:
键和值都是 String 类型
java.util.Properties类: 属性集, 属于Map的双列集合, 继承自Hashtable
构造方法
Properties(): 创建一个Properties集合
可以使用Map接口中的方法
特有成员方法
Object setProperty(String key, String value): 保存/替换键值对
String getProperty(String key): 通过键获取值. 键不存在返回null
Set<String> stringPropertyNames(): 返回键的集合
void store(OutputStream out, String comments): 将集合用字节流写入文件(不能中文),并写入注释
void store(Writer writer, String comments): 将集合用字符流写入文件(可以中文),并写入注释
void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)
Properties: store()存储数据到文件
Properties将数据写入到文件的方法:
void store(OutputStream out, String comments): 将集合用字节流写入文件(不能中文),并写入注释
void store(Writer writer, String comments): 将集合用字符流写入文件(可以中文), 并写入注释
使用步骤:
1.创建Properties集合对象,添加数据
2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
4.释放资源
补充:
属性集(配置文件), 标准的后缀是.properties
配置文件格式要求:
一行一个键值对
键和值中间用=分隔 (标准格式, 但空格分开也行)
#表示单行注释
Properties将数据从文件加载到集合中的方法:
void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)
使用步骤:
1.创建Properties集合对象
2.使用Properties集合对象中的方法load读取保存键值对的文件
3.遍历Properties集合
day10
缓冲流缓冲流的原理缓冲流的原理:
底层也是使用基本流(FileXxx)来读写
但缓冲流内部定义了一个缓冲数组, 在读的时候类似于我们一次读一个数组的方式, 减少了磁盘操作次数, 提高了程序效率
字节缓冲流:
BufferedInputStream 缓冲字节输入流
BufferedOutputStream 缓冲字节输出流
字符缓冲流
BufferedReader 缓冲字符输入流
BufferedWriter 缓冲字符输出流
BufferedOutputStream类: 缓冲字节输出流
构造方法
BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流
BufferedOutputStream(OutputStream out, int size): 使用基本流创建一个缓冲字节输出流, 设置缓冲区大小
使用步骤:
创建FileOutputStream对象, 构造方法中绑定要输出的目的地
创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象, 提高FileOutputStream效率
使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区中
使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷新到文件中
释放资源(会先调用flush方法刷新数据, 第4步可以省略)
BufferedInputStream类: 缓冲字节输入流
构造方法
BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流
BufferedInputStream(InputStream in, int size): 使用基本流创建一个缓冲字节输入流, 设置缓冲区大小
使用步骤:
1.创建FileInputStream对象, 构造方法中绑定要读取的数据源
2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象, 提高FileInputStream效率
3.使用BufferedInputStream对象中的方法 read(), 读取文件
4.释放资源 close()
缓冲流 : 一次读写一个字节数组 效率最高
缓冲字符输出流: BufferedWriter类:
构造方法
BufferedWriter(Writer out): 使用基本流创建一个缓冲字符输出流
BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小
特有方法
void newLine(): 写入一个换行符, 换行符自动根据当前系统确定
BufferedReader类: 缓冲字符输入流
构造方法
BufferedReader(Reader in): 使用基本流创建一个缓冲字符输入流
BufferedReader(Reader in, int size): 使用基本流创建一个缓冲字符输入流, 设置缓冲区大小
特有方法
String readLine(): 一次读一行字符串, "不包含换行符". 读到文件末尾返回null
编码表: 字符和二进制数字的对应规则
字符集和编码表: 字符集包含编码表
ASCII字符集
ASCII编码表
ISO-8859-1字符集:
Latin-1: 拉丁字符. 没有中文. 每个字符由1个byte组成
GB字符集
GB2312编码表: 每个字符由2个byte组成
GBK编码表: 每个字符由2个byte组成
GB18030编码表: 每个字符由1, 2, 4个byte组成
Unicode
UTF-8: ASCII字符占1个byte, 拉丁字符占2个byte, 中文占3个byte, Unicode辅助字符占4个byte
UTF-16
UTF-32
ANSI: 表示使用系统默认编码表
乱码原因: 读写编码不一致
乱码原理: 字符流和转换流的关系
OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁
构造方法
OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流
OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流
write('a') -> "GBK" -> 97 OutputStream out -> 文件
InputStreamReader类: 输入转换流. 字节流通往字符流的桥梁
构造方法
InputStreamReader(InputStream in): 使用默认编码表创建转换流
InputStreamReader(InputStream in, String charsetName): 使用指定编码表创建转换流
序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中
对象转字节
反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象
字节转对象
对象序列化流: ObjectOutputStream
ObjectOutputStream类: 对象字节输出流
构造方法
ObjectOutputStream(OutputStream out)
特有成员方法
void writeObject(Object obj): 将对象写出
注意:
被读写的对象的类, 必须实现 java.io.Serializable 接口, 否则会抛出 NotSerializableException
该类的所有属性也都必须是可序列化的. (实现 java.io.Serializable 接口)
如果某个属性不需要序列化, 则需要用 transient 修饰为瞬态的
如果要将集合序列化, 那么集合中存储的对象也必须是可序列化的
对象反序列化流: ObjectInputStream
ObjectInputStream类: 对象字节输入流
构造方法
ObjectInputStream(InputStream in)
特有成员方法
Object readObject(): 读取对象
transient瞬态关键字: 避免属性序列化
static 修饰的成员变量属于类不属于对象, 所以不能序列化
transient 修饰的成员变量, 不能被序列化
serialVersionUID序列号的作用:
序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.
该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生变化
当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException
打印流PrintStream:
特点:
1. 只有输出流, 没有输入流
2. PrintStream永远不会抛出IOException
3. 有特殊方法 print(), println(), 可以输出任意类型的值
PrintStream类: 字节打印流
构造方法
PrintStream(File file): 创建字节打印流, 输出到一个文件
PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径
注意事项:
如果用 write() 方法, 会查编码表
如果用 print(), println(), 则原样输出
java.lang.System类:
// 静态方法
static void setOut(PrintStream out): 设置System.out的输出目的地为参数的打印流
|
|