耳熟能详的Java反射和IO流,你还记得多少,真的学会了能应对面试吗???
反射
1. 概念
官方解释:反射是指在程序运行过程中,动态的获取类的信息,并且访问
我们通过反射还是获取类的信息(属性,方法,构造方法),然后访问,只不过我们现在不再以new的方式获取
Java中反射相关的API都位于java.lang.reflect包下
万物皆对象
Class 类
Method 方法
Field 属性
Constructor 构造方法
2. 使用反射获取属性
2.1 获取public修饰的属性
getFields() 获取所有的public修饰的属性对象
getField(String name) 根据名字获取单个属性对象
2.2 获取已声明的属性
getDeclaredFields()获取所有已经定义的属性对象,包括private,默认修饰符,protected,public
getDeclaredField(String name)根据名字获取单个属性对象,可以是任意访问修饰符
3. 使用反射获取方法
3.1 获取public修饰的和继承父类的方法
getMethods()获取所有public修饰的方法和继承父类的方法
getMethod()获取单个的方法
3.2获取本类定义的方法
getDeclaredMethod(String name,Class<?>.....parameterTypes>获取单个本类中声明的方法,如果访问权限不足,可以使用setAccessable(true)修改权限
getDeclaredMethods()获取所有本类中已定义的方法
4.使用反射获取构造器
4.1获取所有public修饰的构造器
getConStructors()获取public修饰的所有构造方法
getConstructor(Class.....type)获取单个的构造器对象
4.2 获取本类中定义的构造方法
getDeclaredConstructors()获取本类中定义的所有构造方法
getDeclaredConstructor()获取单个的构造方法
IO流
1.File类
File 类提供了一些用于查看文件信息的方法
package com.qfedu.test4;
import java.io.File;
import java.io.IOException;
/**
* java.io.File类
* 此类提供了一些用于获取文件信息的方法
* 比如 名称 大小 等等
* @author WHD
*
*/
public class TestFile {
public static void main(String[] args) throws IOException {
File file = new File("a.txt");
file.createNewFile(); // 创建一个新文件
System.out.println("文件名" + file.getName());
System.out.println("相对路径" + file.getPath());
System.out.println("绝对路径" + file.getAbsolutePath());
System.out.println("是否存在" + file.exists());
System.out.println("是否是一个文件" + file.isFile());
System.out.println("是否是一个文件夹" + file.isDirectory());
System.out.println("文件大小" + file.length());
System.out.println("删除文件" + file.delete());
File dir = new File("A");
dir.mkdir();
System.out.println("是否是一个文件夹" + dir.isDirectory());
File dir1 = new File("E/F/G");
dir1.mkdirs();
File f = new File("C:\\Users\\WHD\\Desktop\\2103.txt");
f.createNewFile();
}
}
2.字节流
2.1 InputStream
字节流读取类父类,是一个抽象类,提供了各种read方法
2.1.1 FileInputStream
提供了用于读写字节的方法,可以一次读取一个字节,也可以读取一个字节数组
package com.qfedu.test5;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* InputStream
* FileInputStream 字节读取(输入流)流类
* read() 每次读取一个字节 返回值为读取的内容的ascii码值
*
* close() 关闭资源
* available() 获取当前文件可读字节数
*
* 构造方法
* FileInputStream(File file)
* FileInputStream(String name)
* @author WHD
*
*/
public class TestFileInputStream1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
int data = -1;
while((data = fis.read()) != -1) {
System.out.println((char)data);
}
fis.close(); // 关闭资源
}
}
package com.qfedu.test5;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 使用字节流每次读取一个byte数组
* read(byte [] datas) 每次读取指定长度的字节 返回值为读取的长度 读取的内容在byte数组
* @author WHD
*
*/
public class TestFileInputStream2 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("b.txt");
System.out.println(fis.available());
byte [] datas = new byte[fis.available()];
int dataCount = -1;
while((dataCount = fis.read(datas)) != -1) {
// System.out.println(dataCount);
System.out.println(new String(datas, 0, dataCount));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.2 OutputStream
字节写入流父类,抽象类,提供了各种wirte方法
2.2.1 FileOutputStream
字节写入流类,可以一次写入一个字节,也可以一次写入一个字节数组
package com.qfedu.test6;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* OutputStream 父类 抽象类
* FileOutputStream
* write(int chars);
* write(byte [] datas);
* close();
* flush(); 将内存中的内容 刷新到硬盘中 字节流是直接操作硬盘的
* @author WHD
*
*/
public class TestFileOutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("c.txt", true); // 第二个参数为是否追加 默认为false
fos.write(98);
fos.close();
}
}
package com.qfedu.test6;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 每次写入一个字节数组
* @author WHD
*
*/
public class TestFileOutputStream2 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("d.txt", true);
String info = "hello world 世界你好";
fos.write(info.getBytes());
fos.write("你好".getBytes());
fos.close();
}
}
3.字符流
3.1 Reader
字符读取流父类,抽象类。提供了各种read方法。
3.1.1 InputStreamReader
此类提供各种read方法,可以一次读取一个字符,也可以一次读取一个char数组,还支持指定读取的编码格式
package com.qfedu.test1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Reader类抽象类父类
* InputStreamReader子类
* 字符读取流:
* read 每次读取一个字符 返回值为读取的内容
* read(char [] datas) 每次读取一个字符数组 返回值是读取的长度 内容在char数组
*
* close 关闭资源
* @author WHD
*
*/
public class TestInputStreamReader1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
InputStreamReader isr = new InputStreamReader(fis);
int data = -1;
while((data = isr.read()) != -1){
System.out.println((char)data);
}
// 关闭的顺序 先用后关
isr.close();
fis.close();
}
}
package com.qfedu.test1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 每次读取一个字符数组
* @author WHD
*
*/
public class TestInputStreamReader2 {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
char [] chars = new char[5];
int readCount = 0;
while((readCount = isr.read(chars)) != -1) {
// System.out.println(readCount);
System.out.println(chars);
System.out.println(new String(chars, 0, readCount));
System.out.println("========================");
}
// 关闭资源
isr.close();
}
}
package com.qfedu.test1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 使用InputStreamReader构造方法指定编码格式 解决乱码问题
*
* 乱码产生的原因:
* 编码和解码方式不统一 将会产生乱码
* 解决方案:
* 让编码和解码使用一种编码格式就可以了
*
* UTF-8 Unicode编码格式 万国码 支持中文及其他国家的语言
* GBK 国标扩展板 支持大部分的中文简体和繁体
* GB2312 国标2312 支持大部分的中文简体
* ISO-8859-1 最原始的编码格式 用于处理字符串内容乱码
* ANSI在不同的操作系统表示不同的编码格式 在中文Win10 表示 GBK
* @author WHD
*
*/
public class TestInputStreamReader3 {
public static void main(String[] args) throws IOException {
System.getProperties().list(System.out);
InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\Users\\WHD\\Desktop\\2103.txt"),"utf-8");
int data = -1;
while(( data = isr.read()) != -1) {
System.out.println((char)data);
}
// 关闭资源
isr.close();
}
}
3.1.1.1 FileReader
FileReader 此类只能按照本地平台默认的编码格式来读取 不能指定编码
package com.qfedu.test2;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* Reader
* InputStreamReader
* FileReader 此类只能按照本地平台默认的编码格式来读取 不能指定编码
*
* @author WHD
*
*/
public class TestFileReader {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("a.txt");
int data = -1;
while((data = reader.read() )!= -1){
System.out.println((char)data);
}
reader.close();
}
}
package com.qfedu.test2;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* 使用FileReader每次读取一个字符数组
* @author WHD
*
*/
public class TestFileReader2 {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("a.txt");
char [] chs = new char[5];
int dataCount = -1;
while((dataCount = reader.read(chs)) != -1) {
System.out.println(new String(chs,0,dataCount));
}
reader.close();
}
}
3.1.2 BufferedReader
带有缓冲区的字符读取流,提供了独有的读取整行的方法readLine()
package com.qfedu.test2;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class TestBufferedReader {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
// 关闭资源
br.close();
}
}
3.2 Writer
字符写入流父类,抽象类,提供了各种write方法
3.2.1 OutputStreamWriter
字符写入流,可以一次写入一个字符,也可以一次写入一个char数组,可以指定写入的编码格式
package com.qfedu.test3;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
* Writer抽象类父类
* OutputStreamWriter 子类
* write(String str);
*
* OutputStreamWriter 可以指定写入的编码格式
* @author WHD
*
*/
public class TestOutputStreamWriter {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt",true));
osw.write(98);
osw.write("hello world");
osw.write("世界你好".toCharArray());
osw.flush(); // 字符流相当于有一个缓冲区 不是直接操作硬盘的
osw.close();
}
}
package com.qfedu.test3;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
* Writer抽象类父类
* OutputStreamWriter 子类
* write(String str);
*
* OutputStreamWriter 可以指定写入的编码格式
* @author WHD
*
*/
public class TestOutputStreamWriter2 {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c.txt",true),"gbk");
osw.write(98);
osw.write("hello world");
osw.write("世界你好".toCharArray());
osw.flush(); // 字符流相当于有一个缓冲区 不是直接操作硬盘的
osw.close();
}
}
3.2.1.1 FileWriter
FileWriter不能指定编码格式写入
package com.qfedu.test3;
import java.io.FileWriter;
import java.io.IOException;
/**
* Writer
* OutputStreamWriter
* FileWriter不能指定编码格式写入
* @author WHD
*
*/
public class TestFileWriter {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("d.txt", true);
fw.write("hello world");
fw.flush();
fw.close();
}
}
3.2.2 BufferedWriter
此类提供的有换行的方法 newLine()
package com.qfedu.test3;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
* Writer
* BufferedWriter
* 此类提供的有换行的方法 newLine()
* @author WHD
*
*/
public class TestBufferedWriter {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("e.txt")));
bw.write("hello world1\n");
bw.write("hello world2\n");
bw.newLine();
bw.write("世界你好");
bw.flush();
}
}
4.数据流
4.1 DataInputStream读取二进制文件
4.2 DataOutputStream写入二进制文件
读 DataInputStream
写 DataOutputStream
package com.qfedu.test4;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 读取二进制文件
* 读 DataInputStream
* 写 DataOutputStream
* @author WHD
*
*/
public class TestDataStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\WHD\\Desktop\\zs.jpg");
DataInputStream dis = new DataInputStream(fis);
byte [] datas = new byte[fis.available()];
System.out.println(dis.read(datas));
// System.out.println(new String(datas,0,datas.length)); 因为图片是二进制文件 所以不要打印
DataOutputStream dos = new DataOutputStream(new FileOutputStream("copyzs.jpg"));
dos.write(datas);
// 关闭资源
dos.close();
dis.close();
fis.close();
}
}
5.对象流
5.1 序列化和反序列化
序列化:将对象写入到二进制文件中
反序列化:将存有对象的二进制文件读取为对象
注意:可以被序列化的对象所属的类必须实现Serializable接口,此接口是一个空接口,仅仅作为一个标识,表示此接口的实现类可以被序列化。
被transient修饰的属性不能被序列化。
序列化ID
用于判断读取出来的对象 是所属于哪个类的实例 相当于一个唯一表示
可以自动生成默认的1L
也可以随机生成
也可以不写 因为JVM会自动帮我们添加一个
package com.qfedu.test5;
import java.io.Serializable;
/**
* Serializable接口没有方法 只相当于一个标识 标识此类的实现类可以被序列化
* 序列化ID
* 用于判断读取出来的对象 是所属于哪个类的实例 相当于一个唯一表示
* 可以自动生成默认的1L
* 也可以随机生成
* 也可以不写 因为JVM会自动帮我们添加一个
* @author WHD
*
*/
public class Student implements Serializable{
private static final long serialVersionUID = 1656714578162247302L;
private int age;
private String name;
private transient String address; // 被transient修饰的属性 不能被序列化
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student() {
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + ", address=" + address + "]";
}
}
package com.qfedu.test5;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* ObjectInputStream 读取对象流
* ObjectOutputStream 写入对象流
* @author WHD
*
*/
public class TestObjectStream {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("stu.txt"));
Student zhaosi = new Student(20,"赵四");
zhaosi.setAddress("象牙山");
Student guangkun = new Student(20,"广坤");
guangkun.setAddress("铁岭的");
Student dana = new Student(20,"大拿");
dana.setAddress("东北的");
oos.writeObject(zhaosi);
oos.writeObject(guangkun);
oos.writeObject(dana);
oos.flush();
FileInputStream fis = new FileInputStream("stu.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
while(fis.available() > 0) {
Object obj1 = ois.readObject();
if(obj1 instanceof Student) {
Student s = (Student) obj1;
System.out.println(s);
}
}
// Object obj1 = ois.readObject();
// if(obj1 instanceof Student) {
// Student s = (Student) obj1;
// System.out.println(s);
// }
//
//
// Object obj2 = ois.readObject();
// if(obj2 instanceof Student) {
// Student s = (Student) obj2;
// System.out.println(s);
// }
//
// Object obj3 = ois.readObject();
// if(obj3 instanceof Student) {
// Student s = (Student) obj3;
// System.out.println(s);
// }
//
ois.close();
oos.close();
}
}
NIO
NIO是一种非阻塞的、面向缓存的IO流
I0和NIO的区别
(1)IO是面向流的阻塞I0流,NIO是面向缓存的非阻塞IO流
(2)IO的通道是单向的,NIO的管道是双向的
(3)I0流在输入输出数据的时候,在输入输出数据不可用或者没有时候会把线程挂起,发生阻塞,NIO在输入输出数据的时候,是在输入输出的时候还可以执行其他操作,不会等待,所以不会发生阻塞