java resolve是什么?让我们一起来了解一下吧!
原理:
反序列化时,首先获取序列化的类 : desc( 可理解为单例类的class类,但它和JVM加载到内存中的单例class类有不同)因为如果我们的单例类在构造方法中通过实例不为空则抛出异常防止了反射破坏单例,那单例类是不允许再实例化的。而desc类却依然可以实例化。(当我们反序列化一个对象时,永远不会调用其类的构造函数,反序列化后的实例变量与序列化之前的实例变量相同,类变量与当前的类变量相同,如果反序列化时类未被加载则类变量为默认值。)
判断对象是否能实例化。可以则进行实例化,至此单例类进行了第一次实例化,对象名为obj。第一次实例化完成后,通过反射寻找该单例类中的readResolve()方法,没有则直接返回obj对象。有定义readResolve()方法,desc通过invokeReadResolve(Object obj)方法调用readResolve()方法获取单例对象instance,将他赋值给rep,如果单例对象之前已经被实例化过,那么rep就会指向之前实例化的单例对象。如果我们之前没有实例化单例对象,则rep会指向null。
rep与obj进行比较,由于obj是反射获取的对象,当然与rep不等,于是将rep的值instance赋值给obj,将obj返回,返回对象instance也就保证了单例。
java resolve是从序列化中恢复一个单例对象会破坏单例模式,解决方法是添加readResolve() :通过反序列化readObject()方法获取对象时会去寻找readResolve()方法,如果该方法不存在则直接返回新对象,如果该方法存在则按该方法的内容返回对象,以确保如果我们之前实例化了单例对象,就返回该对象。如果我们之前没有实例化单例对象,则会返回null。
实战演练,具体步骤如下所示: package comsingleton; import javaioObjectStreamException; import javaioSerializable; / 懒汉单例设计模式案例 / public class SingletonDemo implements Serializable { / 懒加载 / private static SingletonDemo instance; / 私有构造器 / private SingletonDemo() { // 防止通过反射实例对象而跳过getInstance()方法 if (instance != null) { throw new RuntimeException("Object has been Instance !!!"); } } / 调用方法才加载类,资源利用率高了,但要保证线程安全 / public static synchronized SingletonDemo getInstance() { if (instance == null) { instance = new SingletonDemo(); } return instance; } / 提供readResolve()方法 当JVM反序列化恢复一个新对象时,系统会自动调用readResolve()方法返回指定好的对象 从而保证系统通过反序列化机制不会产生多的Java对象 @return 单例对象 @throws ObjectStreamException 异常 / private Object readResolve() throws ObjectStreamException { return instance; } } package comsingleton; import orgjunitTest; import javaioFileInputStream; import javaioFileOutputStream; import javaioObjectInputStream; import javaioObjectOutputStream; / 单例测试类 / public class SingletonTest { / 测试方法 / @Test public void test() throws Exception { // 获取instance对象 SingletonDemo instance = SingletonDemogetInstance(); // 获取文件输出流 FileOutputStream fileOutputStream = new FileOutputStream("E:\\Testtxt"); // 获取对象输出流 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); // 输出对象 objectOutputStreamwriteObject(instance); // 关闭资源 objectOutputStreamclose(); fileOutputStreamclose(); // 获取对象输入流 ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("E:\\Testtxt")); // 读取对象 Object object = objectInputStreamreadObject(); // 判断两个对象是否相等,返回true/false Systemoutprintln(instance == object); } }
一、超类:
字节流: InputStream(读入流) OutputStream(写出流)
字符流: Reader(字符 读入流) Writer (字符写出流)
二、文件 *** 作流
字节流: FileInputStream ,FileOutputStream
字符流: FileReader, FileWriter(用法与字节流基本相同,不写)
//1指定要读 的文件目录及名称
File file =new File("文件路径");
//2创建文件读入流对象
FileInputStream fis =new FileInputStream(file);
//3定义结束标志,可用字节数组读取
int i =0 ;
while((i = fisread())!=-1){
//i 就是从文件中读取的字节,读完后返回-1
}
//4关闭流
fisclose();
//5处理异常
//1指定要写到的文件目录及名称
File file =new File("文件路径");
//2创建文件读入流对象
FileOutputStream fos =new FileOutputStream(file);
//3定义结束标志
foswrite(要写出的字节或者字节数组);
//4刷新和关闭流
fosflush();
fosclose();
//5处理异常
三、缓冲流:
字节缓冲流: BufferedInputStream,BufferedOutputStream
字符缓冲流:BufferedReader ,BufferedWriter
缓冲流是对流的 *** 作的功能的加强,提高了数据的读写效率。既然缓冲流是对流的功能和读写效率的加强和提高,所以在创建缓冲流的对象时应该要传入要加强的流对象。
//1指定要读 的文件目录及名称
File file =new File("文件路径");
//2创建文件读入流对象
FileInputStream fis =new FileInputStream(file);
//3创建缓冲流对象加强fis功能
BufferedInputStream bis =new BufferedInputStream(fis);
//4定义结束标志,可用字节数组读取
int i =0 ;
while((i = bisread())!=-1){
//i 就是从文件中读取的字节,读完后返回-1
}
//5关闭流
bisclose();
//6处理异常
//1指定要写到的文件目录及名称
File file =new File("文件路径");
//2创建文件读入流对象
FileOutputStream fos =new FileOutputStream(file);
//3创建缓冲流对象加强fos功能
BufferedOutputStream bos=new BufferedOutputStream(fos);
//4向流中写入数据
boswrite(要写出的字节或者字节数组);
//5刷新和关闭流
bosflush();
bosclose();
//6处理异常
四、对象流
ObjectInputStream ,ObjectOutputStream
不同于以上两种类型的流这里只能用字节对对象进行 *** 作原因可以看上篇的编码表比照原理
ObjectOutputStream对象的序列化:
将java程序中的对象写到本地磁盘里用ObjectOutputStream
eg:将Person类的对象序列化到磁盘
创建Person类
注1:此类要实现Serializable接口,此接口为标志性接口
注2:此类要有无参的构造函数
注3:一旦序列化此类不能再修改
class Person implements Serializable{
public Person(){}
}
2创建对象流对象
注:要增强功能可以将传入文件缓冲流
ObjectOutputStream oos =new ObjectOutputStream(
new FileOutputStream(new File("文件路径")));
3写入对象 ,一般会将对象用集合存储起来然后直接将集合写入文件
List<Person> list =new ArrayList<>();
listadd(new Person());
(可以添加多个)
ooswriteObject(list);
4关闭流,处理异常
oosflush();
oosclose();
五、转换流:
这类流是用于将字符转换为字节输入输出,用于 *** 作字符文件,属于字符流的子类,所以后缀为reader,writer;前缀inputstream,outputstream;
注 :要传入字节流作为参赛
InputStreamReader: 字符转换输出流
OutputStreamWriter:字符转换输入流
//1获取键盘输入的字节流对象
inInputStream in =Streamin;
/2用转换流将字节流对象转换为字符流对象,方便调用字符缓冲流的readeLine()方法/
InputStreamReader isr =new InputStreamReader(in);
/5创建字符转换输出流对象osw,方便把输入的字符流转换为字节输出到本地文件。/
OutputStreamWriter osw =new OutputStreamWriter(new
FileOutputStream(new File("文件名")));
/3现在isr是字符流,可以作为参数传入字符缓冲流中/
BufferedReader br =new BufferedReader(isr);
/4可以调用字符缓冲流br的readLine()方法度一行输入文本/
String line =null;
while((line =brreadLine()){
oswwrite(line);//osw是字符流对象,可以直接 *** 作字符串
}
注:InputStreamReader isr =new InputStreamReader(new "各种类型的字节输入流都行即是:后缀为InputStream就行");
OutputStreamWriter osw =new OutputStreamWriter(new
"后缀为OutputStream就行");
六、区别记忆
1对象流是可以读写几乎所有类型的只要是对象就行,而字节字符流,只能读写单个字节字符或者字节字符数组,以上没有读写字节字符数组的;注意对象流只有字节流!
2字符和字节循环读入的结束条件int i=0; (i =fisread())!=-1
用字符数组复制文件(fr 读入流 ,fw写出流),字节流也是相同的用法
int i = 0; char[] c = new char[1024];
while((i = frreade()) !=-1)){
fwwrite(c,0,i);
}
123456
3对象流里面套缓冲流的情景:
new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File(“文件路径”))));
4记忆流及其功能的方法:
前缀表示功能,后缀表示流的类型;
比如说FileInputStream 前缀:File,表示 *** 作的磁盘,后缀:intputstream,表示是字节输入流。
同理 FileReader:表示 *** 作文件的字符流
ObjectInputStream : *** 作对象的字节输入流
5拓展:获取键盘输入的字符的缓冲流的写法:
new BufferedReader(new InputStreamReader(Systemin)));
将字节以字符形式输出到控制台的字符缓冲流的写法:
new BufferedWriter( new OutputStreamWriter(Systemout))
Notes是一个具有Id , RuleID , MainId 属性的javaBean
public static List<Notes> readFromXLS2007(String filePath) {
File excelFile = null;// Excel文件对象
InputStream is = null;// 输入流对象
String cellStr = null;// 单元格,最终按字符串处理
List<Notes> NotesList = new ArrayList<Notes>();// 返回封装数据的List
Notes Notes = null;// 每一个Notes对象
try {
excelFile = new File(filePath);
is = new FileInputStream(excelFile);// 获取文件输入流
XSSFWorkbook workbook2007 = new XSSFWorkbook(is);// 创建Excel2007文件对象
XSSFSheet sheet = workbook2007getSheetAt(0);// 取出第一个工作表,索引是0
// 开始循环遍历行,表头不处理,从1开始
for (int i = 1; i <= sheetgetLastRowNum(); i++) {
Notes = new Notes();// 实例化Notes对象
XSSFRow row = sheetgetRow(i);// 获取行对象
if (row == null) {// 如果为空,不处理
continue;
}
// 循环遍历单元格
for (int j = 0; j < rowgetLastCellNum(); j++) {
XSSFCell cell = rowgetCell(j);// 获取单元格对象
if (cell == null) {// 单元格为空设置cellStr为空串
cellStr = "";
} else if (cellgetCellType() == XSSFCellCELL_TYPE_BOOLEAN) {// 对布尔值的处理
cellStr = StringvalueOf(cellgetBooleanCellValue());
} else if (cellgetCellType() == XSSFCellCELL_TYPE_NUMERIC) {// 对数字值的处理
cellStr = cellgetNumericCellValue() + "";
} else {// 其余按照字符串处理
cellStr = cellgetStringCellValue();
}
// 下面按照数据出现位置封装到bean中
if (j == 0) {
NotessetId(new Double(cellStr)intValue());
} else if (j == 1) {
NotessetRuleId(new Double(cellStr)intValue());
} else if (j == 2) {
NotessetMainId(new Double(cellStr)intValue());
}
}
NotesListadd(Notes);// 数据装入List
}
} catch (IOException e) {
eprintStackTrace();
} finally {// 关闭文件流
if (is != null) {
try {
isclose();
} catch (IOException e) {
eprintStackTrace();
}
}
}
return NotesList;
}
}
//java中使用文件输入流和文件输出流进行文件读写的用例!
Java
package comtestio;
import javaioFile;
import javaioFileInputStream;
import javaioFileNotFoundException;
import javaioFileOutputStream;
import javaioIOException;
import javaioInputStream;
import javaioOutputStream;
/
@author 亚当爱上java
用例内容:文件输入流和文件输入流结合用例,字节流方式
时间:2010-06-20
注意事项:文件输入流和文件输出流都是相对与内存来说的,例如通过程序读取文件时往内存输入数据就是文件输入流
/
public class FileInputOrOutput {
public static void main(String[] args) {
// 文件或者路径名的抽象表现形式,意思就是说之后如果进行 *** 作的话就是全部在这个抽象路径名所指向的文件或者文件加中
File file = new File("e:/testtxt");
File file2 = new File("e:/test1txt");
// 文件字节数的个数
// Systemoutprintln(filelength());
try {
/------------------------------------------读 *** 作部分-----------------------------------------------/
//文件输入流对象
InputStream fis = new FileInputStream(file);
// 文件输入流对象所读取的字节数大小
// Systemoutprintln(fisavailable());
/
1按照一个字节为单位进行读取数据,弊端是遇到中文就会把中文的汉字拆开从而出现乱码
/
// //流对象读出的返回值是每次所读到的一个字符所对应的ascii码值
// int i = fisread();
//
// //如果已经读到文件尾则i==-1,此时终止循环
// while(i!=-1){
// Systemoutprint((char)i);
// 保证每一次循环都继续往后读取一个字符,否则i的值不变会成为死循环
// i = fisread();
// }
/
2按照一个字节数组所指定的大小为单位进行读取,每次最多可以读取数组定义的大小的字节个数
/
// 每次读取都以1K字节作为单位来进行
byte b[] = new byte[1024];
// 流对象读出并返回的是每次读取字节的个数,最大每次读取自己数可以和数组blength相同
// b中存储了每次所读取的所有数据
int i = fisread(b);
String str = "";
// 如果已经读到文件尾则i==-1,此时终止循环
while (i != -1) {
// 把每次读取的字节数组解码为字符串
// 参数1:要解码为字符的字节
// 参数2:要解码的首字符的索引
// 参数3:要解码的字节的个数,如果文件个数大于所设定的一次读取文件的大小时i的取值就是
// blength,否则小于数组的字节大小时则为实际的读取出自己数的大小
str = str + new String(b, 0, i);
// 保证每一次都往文件的下一部分进行读取,否则i值没有变化会成为死循环
i = fisread(b);
}
// Systemoutprint(str);
// 关闭输入流对象
fisclose();
/------------------------------------------写 *** 作部分-----------------------------------------------/
//文件输出流对象
OutputStream fos = new FileOutputStream(file2);
//str是从file所指定的文件中读出的所有内容,将此内容写入另一个文件中
//将字符解码为字节数组
byte b2[] = strgetBytes();
//将解码后的字节数组,通过文件输出流对象写入到缓冲区中
foswrite(b);
//强制将缓冲区中的内容输出到文件中
fosflush();
//关闭输出流对象
fosclose();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
eprintStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
}
}
以上就是关于java resolve全部的内容,包括:java resolve、java的几种IO流读取文件方式、java poi Excel2007里的SXSSFWorkbook怎样读取文件 SXSSFWorkbook只能写吗,那怎样获得要写的内容等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)