java核心技术之IO流(六)DataInputStream和DataOutputStream

最后更新于:2022-04-01 09:58:50

### 说明 DataInputStream和DataOutputStream允许应用程序以与机器无关的方式从底层输入流中读取基本的java数据类型。也就是说,当读取一个数据时,不必关心这个数值是什么字节。 ### 关键方法 ### DataInputStream 构造方法: DataInputStream(InputStream in) 读取数据: readBoolean() readByte() readChar() readInt() readFloat() readDouble() ### DataOutputStream 构造方法: DataOutputStream(OutputStream out) 写入数据的方法: writeBoolean(boolean v) writeByte(int v) writeChar(int v) writeInt(int v) writeFloat(float v) writeDouble(double v) ### 使用Demo 这个Demo是一个使用DataOutputStream向文件中存取数据和使用DataInputStream从文件中读取数据的样例: ~~~ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class DataInputStreamDataOutputStream { public static void testDataInputStream(){ DataInputStream dis = null; try { File fin = new File("DataInputOutputStream.txt"); FileInputStream fis = new FileInputStream(fin); dis = new DataInputStream(fis); System.out.println(dis.readInt()); System.out.println(dis.readBoolean()); System.out.println(dis.readFloat()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(dis != null){ try { dis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //测试DataOutputStream public static void testDataOutputStream(){ DataOutputStream dos = null; try { File fout = new File("DataInputOutputStream.txt"); FileOutputStream fos = new FileOutputStream(fout); dos = new DataOutputStream(fos); dos.writeInt(1); dos.writeBoolean(true); dos.writeFloat((float) 1.203); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(dos != null){ try { dos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } ~~~ 调用方式: ~~~ //测试DataOutputStream DataInputStreamDataOutputStream.testDataOutputStream(); //测试DataInputStream DataInputStreamDataOutputStream.testDataInputStream(); ~~~
';

java核心技术之IO流(五)BufferedReader和BufferedWriter

最后更新于:2022-04-01 09:58:48

### 简单的说明 一般小的字符(char)文件的读取和写入数据,我们使用FileReader和FileWriter类就可以实现了,但是对于大的字符(char)文件的读取和写入数据,性能就会有很大的问题,我们一般选择BufferedReader和BufferedWriter来处理,也就是说BufferedReader和BufferedWriter主要的目的是提高字符(char)文件的内容读取和写入的性能。 ### BufferedReader和BufferedWriter ### BufferedReader类 构造方法: BufferedReader(Reader in) 创建一个有8192的字符(char)的缓存区 BufferedReader(Reader in, int size) 创建一个有size大小字符(char)的缓存区 关键方法: read() read(char[] buffer, int offset, int length) readLine()——读取一行数据 常用使用方式: ~~~ BufferedReader buf = new BufferedReader(new FileReader("file.java")); ~~~ ### BufferedWriter类 构造方法: BufferedWriter(Writer out) 创建一个有8192的字符(char)的缓存区 BufferedWriter(Writer out, int size) 创建一个有size大小字符(char)的缓存区 关键方法: write(int oneChar) write(String str, int offset, int count) write(char[] buffer, int offset, int count) newLine()——插入新的一行 flush() 主要是用来把缓存区的数据刷新到文件中去 常用使用方式: ~~~ BufferedWriter buf = new BufferedWriter(new FileWriter("file.java")); ~~~ ### 一个测试的Demo 定义三个方法: (1)testBufferedWrite方法—测试BufferedWriter BufferedWriter的使用方法: ~~~ //1.创建一个输入字符文件 //2.定义一个FileWriter //3.定义一个BufferedWriter //4.写的操作 //5.关闭对应的流 ~~~ (2)testBufferedReader方法—-向文件读内容 BufferedReader的使用方法: ~~~ //1.创建一个File文件 //2.定义一个FileReader //3.定义一个BufferedReader //4.执行读的操作 读的操作有二种方式,一各是按char来读,一种是按行来说。 一般来说按行来读是更简单,更有效的。 //5.关闭对应的流,可以只关闭最外面的流 ~~~ (3)CopyFile方法—-复制字符文件 ~~~ //1.定义输入和输出的文件 //2.分别定义FileReader,FileWriter //3.分别定义BufferedReader,BufferedWriter //4.实现复制功能 //5.关闭对应 的流,可以只关闭最外面的缓存流就可以 ~~~ ~~~ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class BufferedReaderBufferedWrite { //复制字符文件 public static void CopyFile(String src,String des){ //3.分别定义BufferedReader,BufferedWriter BufferedReader br = null; BufferedWriter bw = null; try { //1.定义二个文件 File fsrc = new File(src); File fdes = new File(des); //2.分别定义FileReader,FileWriter FileReader fr = new FileReader(fsrc); FileWriter fw = new FileWriter(fdes); br = new BufferedReader(fr); bw = new BufferedWriter(fw); //4.复制操作 char[] c = new char[2]; int len; while((len = br.read(c)) != -1){ bw.write(c, 0, len); bw.flush(); } } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally{ //5.关闭对应 的流,可以只关闭最外面的缓存流就可以 if(bw != null){ try { bw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(br != null){ try { br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //测试BufferedReader public static void testBufferedReader(){ //3.定义一个BufferedReader BufferedReader bf = null; try { //1.定义一个文件 File f1= new File("testBufferedWrite.txt"); //2.定义一个FileReader FileReader fr = new FileReader(f1); bf = new BufferedReader(fr); //4.执行读的操作 //方式一 // char[] c = new char[2]; // int len; // while((len = bf.read(c)) != -1){ // System.out.print(c); // } //方式二 String str; while((str = bf.readLine()) != null){ System.out.print(str); System.out.println(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //5.关闭对应的流,可以只关闭最外面的流 if(bf != null){ try { bf.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //测试BufferedWriter public static void testBufferedWrite(){ //3.定义一个BufferedWriter BufferedWriter bw = null; try { //1.定义一个文件 File f1 = new File("testBufferedWrite.txt"); //2.定义一个FileWriter FileWriter fw = new FileWriter(f1); bw = new BufferedWriter(fw); //4.写的操作 String str = "测试BufferedWriter"; bw.write(str); bw.newLine(); bw.write(str); bw.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //5.关闭对应的流 if(bw != null){ try { bw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } ~~~ 调用: ~~~ //BufferedWriter使用样例 BufferedReaderBufferedWrite.testBufferedWrite(); //测试BufferedReader BufferedReaderBufferedWrite.testBufferedReader(); //复制字符文件 BufferedReaderBufferedWrite.CopyFile("testBufferedWrite.txt", "testBufferedWrite_copy.txt"); ~~~ 参考资料: 1.BufferedWriterapi文档 android_sdk_docs_offline/reference/java/io/BufferedWriter.html 2.BufferedReader文档 android_sdk_docs_offline/reference/java/io/BufferedReader.html 3.BufferedOutputStream与BufferedReader视频 [http://edu.csdn.net/course/detail/805/10967?auto_start=1](http://edu.csdn.net/course/detail/805/10967?auto_start=1)
';

java核心技术之IO流(四)BufferedInputStream和BufferedOutputStream

最后更新于:2022-04-01 09:58:46

### 简单的说明 一般小的字节(byte)文件的读取和写入数据,我们使用FileInputStream和FileOutputStream类就可以实现了,但是对于大的字节(byte)文件的读取和写入数据,性能就会有很大的问题,我们一般选择BufferedInputStream和BufferedOutputStream来处理,也就是说BufferedInputStream和BufferedOutputStream主要的目的是提高字节(byte)文件的内容读取和写入的性能。 ### BufferedInputStream和BufferedOutputStream ### BufferedInputStream类 构造方法: BufferedInputStream(InputStream in) 创建一个有32字节的缓存区 BufferedInputStream(InputStream in, int size) 创建一个有size大小字节的缓存区 关键方法: read() read(byte[] buffer, int byteOffset, int byteCount) 常用使用方式: ~~~ BufferedInputStream buf = new BufferedInputStream(new FileInputStream("file.java")); ~~~ ### BufferedOutputStream类 构造方法: BufferedOutputStream(OutputStream out) BufferedOutputStream(OutputStream out, int size) 关键方法: write(int oneByte) write(byte[] buffer, int offset, int length) flush() 主要是用来把缓存区的数据刷新到文件中去 常用使用方式: ~~~ BufferedOutputStream buf = new BufferedOutputStream(new FileOutputStream("file.java")); ~~~ ### 一个测试的Demo 定义三个方法: (1)testBufferedInputStream方法—读取文件内容 BufferedInputStream的使用方法: ~~~ //1.创建一个输入字符文件 //2.定义一个输入流FileInputStream //3.定义一个BufferedInputStream //4.输入操作 //5.关闭对应的流,注意,可以只关闭最外面的流 ~~~ (2)testBufferedOutputStream方法—-往文件写内容 BufferedOutputStream的使用方法: ~~~ //1.创建一个File文件 //2.定义一个输出流 //3.定义一个BufferedOutputStream //4.输出操作 //5.关闭对应的流,注意,可以只关闭最外面的流 ~~~ (3)copyFile方法—-复制文件的方法 ~~~ //1.定义输入和输出的文件 //2.定义二个输入输出流 //3.定义二个输入输出缓存流 //4.实现复制功能 //5.关闭对应的流,缓存流的时候,可以只关闭对应的缓存流就可以,先关输出缓存流,再关输入缓存流 ~~~ ~~~ import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class BufferedInputStreamBufferedOutputStream { //使用BufferedInputStream和BufferedOutputStream,实现文件的复制功能 public static void copyFile(String src,String des,int lenByte){ //3.定义二个输入输出缓存流 BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //1.定义输入和输出文件 File fin = new File(src); File fout = new File(des); //2.定义二个输入输出流 FileInputStream fis = new FileInputStream(fin); FileOutputStream fos = new FileOutputStream(fout); bis = new BufferedInputStream(fis); bos = new BufferedOutputStream(fos); //4.实现复制功能 byte[] b = new byte[lenByte]; int len; while((len = bis.read(b))!= -1){ bos.write(b, 0, len); bos.flush(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //5.关闭对应的流,缓存流的时候,可以只关闭对应的缓存流就可以,先关输出缓存流,再关输入缓存流 if (bos != null) { try { bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (bis != null) { try { bis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //BufferedOutputStream使用样例 public static void testBufferedOutputStream(){ //3.定义一个BufferedOutputStream BufferedOutputStream bos = null; try { //1.定义输出File //File fin = new File("music_01.mp3"); File fout = new File("BufferedOutputStream.txt"); //2.定义一个输出流 FileOutputStream fos = new FileOutputStream(fout); bos = new BufferedOutputStream(fos); //4.输出操作 String str = "BufferedOutputStream使用样例"; bos.write(str.getBytes()); fos.flush(); }catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally{ //5.关闭对应的流,注意,可以只关闭最外面的流 if(bos != null){ try { bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //BufferedInputStream使用样例 public static void testBufferedInputStream(){ //3.定义一个BufferedInputStream BufferedInputStream bis = null; try { //1.定义输入File //File fin = new File("music_01.mp3"); File fin = new File("hello.txt"); //2.定义一个输入流 FileInputStream fis = new FileInputStream(fin); bis = new BufferedInputStream(fis); //4.输入操作 byte[] b = new byte[16]; int len; while((len = bis.read(b)) != -1){ System.out.println(new String(b, 0,len)); } }catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally{ //5.关闭对应的流,注意,可以只关闭最外面的流 if(bis != null){ try { bis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } ~~~ 调用: ~~~ //BufferedInputStream使用样例 BufferedInputStreamBufferedOutputStream.testBufferedInputStream(); //BufferedOutputStream使用样例 BufferedInputStreamBufferedOutputStream.testBufferedOutputStream(); //使用BufferedInputStream和BufferedOutputStream,实现文件的复制功能 long t1 = System.currentTimeMillis(); BufferedInputStreamBufferedOutputStream.copyFile("music_01.mp3","music_02.mp3",1024);//10M大小的音乐 long t2 = System.currentTimeMillis(); System.out.print("复制文件消耗的时间:"+(t2 - t1));//10-4437 100-431 1024-60 ~~~ 说明: 测试来复制一个10M大小的音乐文件(music_01.mp3),使用缓存流在一次复制10byte时要4437毫秒,一次复制100byte时要431毫秒,一次复制1024byte时要60毫秒。 参考资料: 1.BufferedOutputStream api文档 android_sdk_docs_offline/reference/java/io/BufferedOutputStream.html 2.BufferedInputStream文档 android_sdk_docs_offline/reference/java/io/BufferedInputStream.html 3.BufferedOutputStream与BufferedInputStream视频 [http://edu.csdn.net/course/detail/805/10967?auto_start=1](http://edu.csdn.net/course/detail/805/10967?auto_start=1)
';

java核心技术之IO流(三)FileReader和FileWriter

最后更新于:2022-04-01 09:58:44

### 简单的说明 从字符类型(char)的文件中读取和写入数据,我们要使用FileWriter和FileReader类来实现。 ### FileWriter和FileReader ### FileWriter类 构造方法: FileWriter(String filename) FileWriter(File file) 关键方法: write(int oneChar) write(char[] buffer, int offset, int count) ### FileReader类 构造方法: FileReader(String filename) FileReader(File file) 关键方法: read() read(char[] buffer, int offset, int count) ### 一个测试的Demo 定义三个方法: (1)testFileReader方法—读取文件内容 FileReader的使用方法: ~~~ //1.创建一个输入字符文件 //2.创建一个FileReader对象 //3.调用read方法,读取内容数据 //4. 关闭对应的流 ~~~ (2)testFileWriter方法—-往文件写内容 FileWriter的使用方法: ~~~ //1.创建一个File文件 //2.创建一个FileWriter对象 //3.调用write方法写入数据 //4.关闭对应的输出流 ~~~ (3)copyByFileReaderFileWriter方法—-复制文件的方法 ~~~ //1.定义输入和输出的文件 //2.定义输入流和输出流的对象 //3.执行复制操作 //4.关闭对应的流,先关输出流,后关输入流 ~~~ ~~~ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class FileReaderFileWriter { //同时使用FileReader和FileWriter,实现二个文本文件的复制 public static void copyByFileReaderFileWriter(String src,String des){ //2.定义二个字符流,输入流,输出流 FileReader fr = null; FileWriter fw = null; try { //1.定义二个文件,一个输入,一个输出 File fin = new File(src); File fout = new File(des); fr = new FileReader(fin); fw = new FileWriter(fout); //3.复制操作 char[] c = new char[20]; int len; while((len = fr.read(c)) != -1){ fw.write(c, 0, len); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //4. 关闭对应的流,先关输出流,再关输入流 if(fw != null){ try { fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(fr != null){ try { fr.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //FileWriter使用样例---处理字符 public static void testFileWriter(){ //2.定义一个FileWriter对象 FileWriter fw = null; try { //1.定义一个输出字符文件 File f1 =new File("hello_FileWriter.txt"); fw = new FileWriter(f1); //3.输出操作 String str = "我是中国人,我爱打dota,还爱搞机"; fw.write(str); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally{ //4.关闭对应的流 if(fw != null){ try { fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //FileReader使用样例---处理字符 public static void testFileReader(){ //2.定义一个FileReader FileReader fr = null; try { //1.定义一个输入字符文件 File f1 =new File("hello.txt"); fr = new FileReader(f1); //3.读入操作 char[] c = new char[10]; int len; while((len = fr.read(c)) != -1){ System.out.print(new String(c,0,len)); } }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //4.关闭对应的流 if(fr != null){ try { fr.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } ~~~ 调用: ~~~ //FileReader使用样例---处理字符 FileReaderFileWriter.testFileReader(); //FileWriter使用样例---处理字符 FileReaderFileWriter.testFileWriter(); //同时使用FileReader和FileWriter,实现二个文本文件的复制 FileReaderFileWriter.copyByFileReaderFileWriter("hello_FileWriter.txt", "hello_FileWriter_copy.txt"); ~~~ 参考资料: 1.FileWriter api文档 android_sdk_docs_offline/reference/java/io/FileWriter.html 2.FileReader文档 android_sdk_docs_offline/reference/java/io/FileReader.html 3.FileWriter与FileReader视频 [http://edu.csdn.net/course/detail/805/10966?auto_start=1](http://edu.csdn.net/course/detail/805/10966?auto_start=1)
';

java核心技术之IO流(二)FileInputStream和FileOutputStream

最后更新于:2022-04-01 09:58:41

### 简单的说明 从文件中读取和写入数据,我们要使用FileInputStream和FileOutputStream类来实现。只是要注意的是,这二个类处理的是字节(byte)型文件。 ### FileInputStream和FileOutputStream ### FileInputStream类 构造方法: FileInputStream(String path) FileInputStream(File file) 关键方法: read() read(byte[] buffer, int byteOffset, int byteCount) ### FileOutputStream类 构造方法: FileOutputStream(String path) FileOutputStream(File file) 关键方法: write(int oneByte) write(byte[] buffer, int byteOffset, int byteCount) ### 一个测试的Demo 定义三个方法: (1)testFileInputStream方法—读取文件内容 FileInputStream的使用方法: ~~~ //1.创建一个File对象 //2.创建一个FileInputStream对象 //3.调用read方法,读取内容数据 //4. 关闭对应的流 ~~~ (2)testFileOutputStream方法—-往文件写内容 FileOutputStream的使用方法: ~~~ //1.创建一个File文件 //2.创建一个FileOutputStream对象 //3.调用write方法写入数据 //4.关闭对应的输出流 ~~~ (3)copyFile方法—-复制文件的方法 ~~~ //1.定义输入和输出的文件 //2.定义输入流和输出流的对象 //3.执行复制操作 //4.关闭对应的流,先关输出流,后关输入流 ~~~ ~~~ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileInputStreamFileOutputStream { //5.同时使用FileOutputStream和FileInputStream,实现二个文件的复制 //参数src为输入文件,参数des为输出文件,byteLength为每次复制的字节数 public static void copyFile(String src,String des,int byteLength){ FileInputStream fis = null; FileOutputStream fos = null; try { //定义输入和输出的文件 File fin = new File(src); File fout = new File(des); //定义输入流和输出流的对象 fis = new FileInputStream(fin); fos = new FileOutputStream(fout); //3.执行复制操作 byte[] b = new byte[byteLength]; int len; while ((len = fis.read(b)) != -1) { fos.write(b, 0, len); } }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //4.关闭对应的流,先关输出流,后关输入流 if (fos != null) { try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(fis != null){ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //4.FileOutputStream的使用 public static void testFileOutputStream(){ //2.创建一个FileOutputStream对象 FileOutputStream fos = null; try { //创建一个File文件 File f1 = new File("file_output_stream.txt"); fos = new FileOutputStream(f1); String str= new String("test FileOutputStream"); //调用write方法写入数据 fos.write(str.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(fos != null){ //关闭对应的输出流 fos.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //3.FileInputStream的使用 public static void testFileInputStream(){ //2.创建一个FileInputStream对象 FileInputStream fis = null; try { //1.创建一个File对象 File f1 = new File("hello.txt"); fis = new FileInputStream(f1); byte[] b = new byte[10] ; int len; //3.调用read方法,读取内容数据 while ((len = fis.read(b))!= -1) { //System.out.print(b.toString()); for(int i=0;i<len;i++){ System.out.print((char)b[i]); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { //4. 关闭对应的流 fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } ~~~ 调用: ~~~ //3.FileInputStream的使 FileInputStreamFileOutputStream.testFileInputStream(); //4.FileOutputStream的使用 FileInputStreamFileOutputStream.testFileOutputStream(); //5.同时使用FileOutputStream和FileInputStream,实现二个文件的复制 long t1 = System.currentTimeMillis(); FileInputStreamFileOutputStream.copyFile("data.bmp","data_01.bmp",10); long t2 = System.currentTimeMillis(); System.out.print("复制文件消耗的时间:"+(t2 - t1));//100-60 10 -551 ~~~ 参考资料: 1.FileInputStream api文档 android_sdk_docs_offline/reference/java/io/FileInputStream.html 2.FileOutputStreamapi文档 android_sdk_docs_offline/reference/java/io/FileOutputStream.html 3.FileOutputStream与FileInputStream 视频
';

java核心技术之IO流(一)File类

最后更新于:2022-04-01 09:58:39

### File类的说明 File类是java.io包中对应着硬盘中的一个文件或网络中的一个资源,可以表示一个文件(.doc .xls .mp3 .avi .jpg .dat等类型),也可以表示一个文件目录。 File类的对象是与平台无关的,File类针对文件或文件目录,只能进行新建,删除,重命名,上层目录等操作,如果涉及到访问文件的内容,File是无能为力,只能使用IO流来实现。我们常把File类的对象做为形参传递给相应的IO流的构造方法中。 ### 关键方法 构造方法: ~~~ File(String path) 使用文件路径名path创建一个File对象 File(URI uri) 使用一个文件的uri创建一个File对象 File(File dir, String name) 使用一父文件dir和文件名name创建一个File对象 File(String dirPath, String name) 使用父文件名dirPath和文件名name创建一个File对象 ~~~ 常用方法 | 方法名 | 说明 | |-----|-----| | getName() | 获取文件名 | | getAbsolutePath() | 获取文件绝对路径 | | getParent() | 获取文件的父路径名 | | lastModified() | 获取最后修改时间 | | length() | 获取文件大小 | | canRead() | 获取文件是否可读 | | canWrite() | 获取文件是否可写 | | mkdir() | 创建文件夹 | | exists() | 文件是否存在 | | createNewFile() | 创建一个新文件 | 关键变量: separator 文件路径的分割符(“\”),这个变量可以更好的支持跨平台的文件名表示 ### File的Demo代码 这个Demo有三个方法: BaseInfo()—–显示文件的基本信息,如名字,大小,路径,修改时间等等。 showFiles(File file)—–显示文件目录下的文件名(不包括子目录下的文件) showAllFiles(File file)—–显示文件目录下的文件名(包括子目录下的文件) ~~~ import java.io.File; import java.io.IOException; import java.util.Date; public class FileDemo { //文件的基本信息 public static void BaseInfo(){ System.out.println("BaseInfo()"); File file = new File("test.txt"); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("file.getName(): "+file.getName()); //C:\Documents and Settings\All Users\workspace\IODemo\test.txt System.out.println("file.getAbsolutePath(): "+file.getAbsolutePath()); System.out.println("file.getParent(): "+file.getParent()); System.out.println("new Date(file.lastModified()): "+ new Date(file.lastModified())); System.out.println("file.length(): "+ file.length()); System.out.println("file.canRead(): "+ file.canRead()); System.out.println("file.canWrite(): "+ file.canWrite()); System.out.println("file.pathSeparator "+file.pathSeparator);//; System.out.println("file.separator "+file.separator);//file.separator---路径分割符(\) File file2 = new File("Demo1"); file2.mkdir(); } //显示文件目录下的文件名(不包括子目录下的文件) public static void showFiles(File file){ System.out.println("\nshowFiles: "+file.getName()); String[] strs = file.list(); for (int i = 0; i < strs.length; i++) { System.out.println("文件"+i+"的名称:"+strs[i]); } } //显示文件目录下的文件名(包括子目录下的文件) public static void showAllFiles(File file){ System.out.print(file.getName()+"/"); File[] f1 = file.listFiles(); if(f1 != null && f1.length > 0){ for (int i = 0; i < f1.length; i++) { //System.out.println("文件"+i+"名字: "+f1[i].getName()); if(f1[i] != null){ if(f1[i].isDirectory()){ if(f1[i] != null){ System.out.print("/"); showAllFiles(f1[i]); } }else{ if(i == 0){ System.out.println(" "); } System.out.println("文件"+i+"名字: "+f1[i].getName()); } } } } } } ~~~ 调用: ~~~ //1.File的一个基本信息 FileDemo.BaseInfo(); //2.显示文件目录下的文件名(不包括子目录下的文件) File f1 = new File("C:\\Documents and Settings"); FileDemo.showFiles(f1); //3.显示文件目录下的文件名(包括子目录下的文件) FileDemo.showAllFiles(f1); ~~~ 输出信息: ~~~ BaseInfo() file.getName(): test.txt file.getAbsolutePath(): C:\Documents and Settings\All Users\workspace\IODemo\test.txt file.getParent(): null new Date(file.lastModified()): Thu Oct 15 20:05:48 CST 2015 file.length(): 0 file.canRead(): true file.canWrite(): true file.pathSeparator ; file.separator \ showFiles: Documents and Settings 文件0的名称:All Users 文件1的名称:Default User 文件2的名称:LocalService 文件3的名称:NetworkService 文件4的名称:user.com ................. ~~~ 参考资料: 1.File api文档 [http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4](http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4) 2.java io视频 [http://edu.csdn.net/course/detail/805/10961?auto_start=1](http://edu.csdn.net/course/detail/805/10961?auto_start=1)
';

java核心技术之reflect(一):一个系统学习reflect的Demo(精)

最后更新于:2022-04-01 09:58:37

### 为什么写这篇文章 reflect是java的一个关键技术,以前,我也只是零星的知道一些点,也会几下三脚猫的reflect使用,但是没有系统的掌握此知识点。 正好这二天看到CSDN学院中有一个宋红康老师的视频–<<[java基础核心技术:Java反射机制(day19-day20)](http://edu.csdn.net/course/detail/809)>>,看完之后受益匪浅啊(点个赞),如果你对reflect不熟,强烈建议大家好好的看看。 看完视频后,我花了点时间,也是参考此视频写了一个Demo,相信应该在此Demo中把reflect系统的学习。 ### reflect的几个关键点 reflect是java的反射机制,功能十分强大。 ### 关键一:包java.lang.reflect 在java的java.lang.reflect包中提供了对该功能的支持。 我可以查看java.lang.reflect包,可以看到下面几个关键的类: | 关键类 | 说明 | |-----|-----| | Constructor-构造类 | This class represents a constructor. | | Field-属性类 | This class represents a field. | | Method-方法类 | This class represents a method. | | Modifier-修饰符类 | This class provides static methods to decode class and member modifiers. | ### 关键二:类java.lang.Class 而reflect的源头是java.lang.Class类,Class类是reflect的总导演,所有java类都继承Object类,在Object类中有getClass()方法,该方法返回一个类型为Class的对象。如代码: ~~~ Class c = persion.getClass();//persion为类Persion的一个对象 ~~~ java.lang.Class类的几个关键方法: | 关键方法 | 说明 | |-----|-----| | getPackage() | 返回包的路径 | | getName() | 返回类的名称 | | getSuperclass() | 返回父类 | | getInterfaces() | 返回其实现的接口 | | getConstructors() | 返回其所有的public构造方法 | | getConstructors(Class… parameterTypes) | 返回其指定参数的public构造方法 | | getDeclaredConstructors() | 返回其所有声明的构造方法,包括private构造方法 | | getDeclaredConstructors(Class… parameterTypes) | 返回其指定参数的构造方法,包括private构造方法 | | getMethods() | 返回其所有的public的方法,包括其父类的public方法 | | getMethod(String name, Class… parameterTypes) | 返回其指定的public的方法 | | getDeclaredFields() | 返回其声明的所有的方法,包括private类型的方法 | | getDeclaredMethod(String name, Class… parameterTypes) | 返回其指定参数的方法,包括private类型的方法 | | getFields() | 返回其所有的public属性,包括其父类的public属性 | | getField(String name) | 返回其指定的public属性,包括其父类的public属性 | | getDeclaredFields() | 返回其声明的所有的属性,包括其private类型的属性 | | getDeclaredField(String name) | 返回其指定的属性,包括其private类型的属性 | | getClasses() | 返回其public的内部类 | | getDeclaredClasses() | 返回其所有的内部类,包括private类型的内部类 | ### 关键三:类Constructor —–java.lang.reflect.Constructor 访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。如: ~~~ c.getDeclaredConstructor(String.class,int.class); c.getDeclaredConstructor(new Class[]{String.class,int.class}); ~~~ Constructor类的常用方法: | 关键方法 | 说明 | |-----|-----| | isVarArgs() | 查看该构造方法是否带有可变数量的参数 | | getParameterTypes() | 返回构造方法的参数列表 | | getExceptionTypes() | 返回构造方法的异常列表 | | newInstance(Object… args) | 返回该构造方法创建的类的对象 | | setAccessible(boolean flag) | 让private类型的构造方法可以创建类的对象 | | getModifiers() | 返回构造方法的类型 | ### 关键四:类Field —–java.lang.reflect.Field 访问指定的属性,需要根据该属性的名称来访问。如: ~~~ c.getDeclaredField("name_field"); ~~~ Field类的常用方法: | 关键方法 | 说明 | |-----|-----| | getName() | 返回成员变量的名称 | | getType() | 返回成员变量的类型 | | get(Object object) | 返回指定对象object的成员变量的值 | | set(Object object, Object value) | 给指定对象object的成员变量设置value值 | | setAccessible(boolean flag) | 让private类型的成员变量拥有public权限 | | getModifiers() | 返回成员变量的类型 | ### 关键五:类Method —– java.lang.reflect.Method 访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。如: ~~~ c.getDeclaredMethod("method_name",String.class,int.class); c.getDeclaredMethod("method_name",new Class[]{String.class,int.class}); ~~~ Method类的常用方法: | 关键方法 | 说明 | |-----|-----| | getName() | 返回该方法的名称 | | getParameterTypes() | 返回方法的参数列表 | | getReturnType() | 返回该方法的返回值类型 | | getExceptionTypes() | 返回方法的异常列表 | | getModifiers() | 返回方法的类型 | | isVarArgs() | 查看该方法是否带有可变数量的参数 | | invoke(Object receiver, Object… args) | 用入口参数来调用指定对象的方法 | | setAccessible(boolean flag) | 让private类型的方法拥有public权限 | ### reflect的作用 - 在运行时判断任意一个对象所属的类 - 在运行时构造任意一个类的对象 - 在运行时判断任意一个类的完整结构 如属性,方法,构造方法,父类等等 - 在运行时调用任意一个类的对象的属性和方法 - 生成动态代理 ### reflect的详细使用指南 ### 创建对应的Class实例 java.lang.Class 反射的源头,反射涉及到的类都在java.lang.reflect目录下,如Field,Method,ConstructorType等等。 实例化Class的方法(4种方法): - 调用运行时类的.class属性 ~~~ c = Persion.class; System.out.println("方法一 : 调用运行时类的.class属性: "+c.toString()); ~~~ - 通过运行时类的对象,调用getClass()方法 ~~~ c = persion.getClass(); System.out.println("方法二 : 通过运行时类的对象,调用getClass()方法: "+c.toString()); ~~~ - 调用Class的静态方法forName(String className) ~~~ c = Class.forName(Persion.class.getName().toString()); System.out.println("方法三 : 调用Class的静态方法forName(String className): "+c.toString()); ~~~ - 通过类的加载器 ~~~ //ClassLoader classLoader = this.getClass().getClassLoader(); ClassLoader classLoader = Persion.class.getClassLoader(); c = classLoader.loadClass(className); System.out.println("方法四:通过类的加载器: "+c.toString()); ~~~ ### 有了Class实例之后,可以做什么? - 可以创建对应的运行时类的对象 方法一:调用Class的newInstance方法 方法二:调用指定的构造器创建运行时类的对象 - 可以获取对应的运行时类的完整结构 如属性,方法,构造方法,包,父类,接口,内部类等等 - 可以调用对应的运行时类的指定结构 (如指定的属性,方法,构造方法) - 动态代码 反射的应用,体会反射的动态性。 ### 这个Demo如何一一破解reflect的关键点 ### Demo的几个相关类 在这个Demo中,我们定义一个Creature 类,类中定义了一个public类型的变量weight和private类型的变量color,一个内部类InnerCreature。 ~~~ package com.java.reflect.demo; public class Creature { public int weight; private int color; @Override public String toString() { return "Creature [weight=" + weight + ", color=" + color + "]"; } public Creature(){ super(); } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } private int getColor() { return color; } private void setColor(int color) { this.color = color; } //内部类 public class InnerCreature{ } } ~~~ 再定义一个接口ISpeakLister : ~~~ package com.java.reflect.demo; public interface ISpeakLister { public void speak(String talk); } ~~~ 定义一个Person类: 这个类非常简单,其父类是Creature,实现了ISpeakLister和Serializable接口,包括了public类型的,private类型的,static类型的属性,public和private类型的构造方法,public,static和private类型的方法,public和private类型的内部类。 ~~~ package com.java.reflect.demo; import java.io.Serializable; public class Person extends Creature implements ISpeakLister,Serializable{ private String name; private int age; public int id; public static String weather = "今天天气好晴朗!!"; public Person(){ super(); System.out.println("Person--Person()"); } public Person(String name,int age,int id){ super(); this.name = name; this.age = age; this.id = id; System.out.println("Person--Person(String name,int age,int id)"); } private Person(String name){ super(); this.name = name; } private String getName() { return name; } private void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public static void showWeather(){ System.out.println("weather: "+ weather); } @Override public String toString() { return "Persion [name=" + name + ", age=" + age + ", id=" + id +",weather="+weather+ "]---"+super.toString(); } @Override public void speak(String talk) { // TODO Auto-generated method stub System.out.println("talk: "+ talk); } //inner class public class innerClass { } private class innerPriClass{ } } ~~~ ### reflect的使用 reflect使用,需要对应的Class对象,对应的类的对象,为了方便,我们定义一个变量保存类的类名。 ### 定义Class变量c,Person对象person和类名: ~~~ private static Class c; private static Person person = new Person(); private static String className = "com.java.reflect.demo.Person"; ~~~ ### 实例化Class的方法(4种方法) ~~~ //实例化Class的方法(4种方法): //java.lang.Class 反射的源头 public static void createClass() throws ClassNotFoundException{ System.out.println(" "); System.out.println("createClass()"); //方法一 : 调用运行时类的.class属性 c = Person.class; System.out.println("方法一 : 调用运行时类的.class属性: "+c.toString()); //方法二 : 通过运行时类的对象,调用getClass()方法 c = person.getClass(); System.out.println("方法二 : 通过运行时类的对象,调用getClass()方法: "+c.toString()); //方法三 : 调用Class的静态方法forName(String className) c = Class.forName(Person.class.getName().toString()); //c = Class.forName(className); System.out.println("方法三 : 调用Class的静态方法forName(String className): "+c.toString()); //方法四:通过类的加载器 // ClassLoader classLoader = this.getClass().getClassLoader(); ClassLoader classLoader = Person.class.getClassLoader(); c = classLoader.loadClass(className); System.out.println("方法四:通过类的加载器: "+c.toString()); } ~~~ 对应的输出信息: ~~~ createClass() 方法一 : 调用运行时类的.class属性: class com.java.reflect.demo.Person 方法二 : 通过运行时类的对象,调用getClass()方法: class com.java.reflect.demo.Person 方法三 : 调用Class的静态方法forName(String className): class com.java.reflect.demo.Person 方法四:通过类的加载器: class com.java.reflect.demo.Person ~~~ ### 创建对应的运行时类的对象 ~~~ //创建对应的运行时类的对象 public static void createInstance(Class c) throws Exception{ //方法一:调用Class的newInstance方法创建运行时类的对象 System.out.println(" "); System.out.println("createInstance()"); person = (Person)c.newInstance(); System.out.println("方法一:调用Class的newInstance方法创建运行时类的对象 --person: "+person); //方法二:调用指定的构造器创建运行时类的对象 //我们指定public类型的构造方法Person(String name,int age,int id)来创建对象 Constructor constructor = c.getDeclaredConstructor(String.class,int.class,int.class); person = (Person) constructor.newInstance("xxx",10,1); System.out.println("方法二:调用指定的构造器(public)创建运行时类的对象 --person: "+person); //我们指定private类型的构造方法Person(String name)来创建对象 constructor = c.getDeclaredConstructor(String.class); constructor.setAccessible(true); person = (Person) constructor.newInstance("****"); System.out.println("方法二:调用指定的构造器(private)创建运行时类的对象 --person: "+person); } ~~~ 输出信息: ~~~ createInstance() Person--Person() 方法一:调用Class的newInstance方法创建运行时类的对象 --person: Persion [name=null, age=0, id=0,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] Person--Person(String name,int age,int id) 方法二:调用指定的构造器(public)创建运行时类的对象 --person: Persion [name=xxx, age=10, id=1,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] 方法二:调用指定的构造器(private)创建运行时类的对象 --person: Persion [name=****, age=0, id=0,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] ~~~ 输出信息分析: 我们调用Class类的newInstance(),会直接调用Class类的无参构造方法来生成类的对象,也可以调用Class类的getDeclaredConstructor方法来获取Class类的指定构造方法,再调用Constructor类的newInstance方法来生成类的对象。 ### 获取对应的运行时类的完整结构 #### 获取类的构造方法 ~~~ private static void getConstructs(Class c) { // TODO Auto-generated method stub System.out.println(" "); System.out.println("getConstructs"); //getConstructors 此方法为获取类的public的构造方法 System.out.println("getConstructors为获取类的public的构造方法 "); Constructor[] constructors1 = c.getConstructors(); for(int i=0;i<constructors1.length;i++){ System.out.println("constructors ["+i+"] :"+constructors1[i]); } //getDeclaredConstructors为获取类本身自己定义的所有构造方法 System.out.println("getDeclaredConstructors此方法为获取类本身自己定义的所有构造方法 "); Constructor[] constructors2 = c.getDeclaredConstructors(); for(int i=0;i<constructors2.length;i++){ System.out.println("constructors ["+i+"] :"+constructors2[i]); } } ~~~ 输出信息: ~~~ getConstructs getConstructors 此方法为获取类的public的构造方法 constructors [0] :public com.java.reflect.demo.Person() constructors [1] :public com.java.reflect.demo.Person(java.lang.String,int,int) getDeclaredConstructors 此方法为获取类本身自己定义的所有构造方法 constructors [0] :public com.java.reflect.demo.Person() constructors [1] :private com.java.reflect.demo.Person(java.lang.String) constructors [2] :public com.java.reflect.demo.Person(java.lang.String,int,int) ~~~ #### 获取类的方法 ~~~ //获取类的方法 private static void getMethods(Class c) { // TODO Auto-generated method stub System.out.println(" "); System.out.println("getMethods"); //getMethods 此方法为获取类的public方法,包括父类的public方法 System.out.println("getMethods 此方法为获取类的public方法,包括父类的public方法 "); Method[] method1 = c.getMethods(); for(int i=0;i<method1.length;i++){ System.out.println("method1 ["+i+"] :"+method1[i]); } //getDeclaredMethods 此方法为获取类本身声明的所有方法,包括private System.out.println(" "); System.out.println("getDeclaredMethods 此方法为获取类本身声明的所有方法,包括private "); Method[] method2 = c.getDeclaredMethods(); for(int i=0;i<method2.length;i++){ System.out.println("method2 ["+i+"] :"+method2[i]); } } ~~~ 输出信息: ~~~ getMethods getMethods 此方法为获取类的public方法,包括父类的public方法 method1 [0] :public void com.java.reflect.demo.Person.setAge(int) method1 [1] :public static void com.java.reflect.demo.Person.showWeather() method1 [2] :public int com.java.reflect.demo.Person.getAge() method1 [3] :public void com.java.reflect.demo.Person.setId(int) method1 [4] :public void com.java.reflect.demo.Person.speak(java.lang.String) method1 [5] :public java.lang.String com.java.reflect.demo.Person.toString() method1 [6] :public int com.java.reflect.demo.Person.getId() method1 [7] :public int com.java.reflect.demo.Creature.getWeight() method1 [8] :public void com.java.reflect.demo.Creature.setWeight(int) method1 [9] :public final native java.lang.Class java.lang.Object.getClass() method1 [10] :public native int java.lang.Object.hashCode() method1 [11] :public boolean java.lang.Object.equals(java.lang.Object) method1 [12] :public final native void java.lang.Object.notify() method1 [13] :public final native void java.lang.Object.notifyAll() method1 [14] :public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException method1 [15] :public final void java.lang.Object.wait() throws java.lang.InterruptedException method1 [16] :public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException getDeclaredMethods 此方法为获取类本身声明的所有方法,包括private method2 [0] :public void com.java.reflect.demo.Person.setAge(int) method2 [1] :public static void com.java.reflect.demo.Person.showWeather() method2 [2] :public int com.java.reflect.demo.Person.getAge() method2 [3] :public void com.java.reflect.demo.Person.setId(int) method2 [4] :public void com.java.reflect.demo.Person.speak(java.lang.String) method2 [5] :public java.lang.String com.java.reflect.demo.Person.toString() method2 [6] :private java.lang.String com.java.reflect.demo.Person.getName() method2 [7] :public int com.java.reflect.demo.Person.getId() method2 [8] :private void com.java.reflect.demo.Person.setName(java.lang.String) ~~~ #### 获取类的属性 ~~~ //获取类的属性 private static void GetFields(Class c) { // TODO Auto-generated method stub System.out.println(" "); System.out.println("GetFields"); //getFields 此方法为获取类的public属性,包括父类的public属性 System.out.println("getFields 此方法为获取类的public属性,包括父类的public属性 "); Field[] field1 = c.getFields(); for(int i=0;i<field1.length;i++){ System.out.println("field1 ["+i+"] :"+field1[i]); } System.out.println(" "); //getDeclaredFields 此方法为获取类的本身声明的所有属性,包括private System.out.println("getDeclaredFields 此方法为获取类的本身声明的所有属性,包括private "); Field[] field2 = c.getDeclaredFields(); for(int i=0;i<field2.length;i++){ System.out.println("field2 ["+i+"] :"+field2[i]); } } ~~~ 信息输出: ~~~ GetFields getFields 此方法为获取类的public属性,包括父类的public属性 field1 [0] :public int com.java.reflect.demo.Person.id field1 [1] :public static java.lang.String com.java.reflect.demo.Person.weather field1 [2] :public int com.java.reflect.demo.Creature.weight getDeclaredFields 此方法为获取类的本身声明的所有属性,包括private field2 [0] :private java.lang.String com.java.reflect.demo.Person.name field2 [1] :private int com.java.reflect.demo.Person.age field2 [2] :public int com.java.reflect.demo.Person.id ~~~ #### 获取类的其它信息 如包,父类,接口,内部类等等 ~~~ //获取类的其它信息,如包,父类,接口,内部类等等 private static void getClassOtherInfo(Class c) { // TODO Auto-generated method stub System.out.println(" "); System.out.println("getClassOtherInfo"); //获取类的包 String p = c.getPackage().toString(); System.out.println("类的包名:"+p); //获取类的父类 Class parentClass = c.getSuperclass(); System.out.println("类的父类:"+parentClass.getName()); //获取类的接口 Class[] interfaces =c.getInterfaces(); if(interfaces.length >0){ System.out.println("类的接口:"); for(int i=0;i<interfaces.length;i++){ System.out.println("interfaces["+i+"] :"+interfaces[i]); } } //获取类的内部类 //getDeclaredClasses方法获取类本身定义的所有内部类,包括private Class[] innerClass1 =c.getDeclaredClasses(); if(innerClass1.length >0){ System.out.println("类的所有内部类 ,包括private:"); for(int i=0;i<innerClass1.length;i++){ System.out.println("innerClass1["+i+"] :"+innerClass1[i]); } } //同理getClasses方法获取类的public内部类,包括父类的public内部类 Class[] innerClass2 =c.getClasses(); if(innerClass2.length >0){ System.out.println("类的public内部类,包括父类的public内部类:"); for(int i=0;i<innerClass2.length;i++){ System.out.println("innerClass2["+i+"] :"+innerClass2[i]); } } } ~~~ 输出信息: ~~~ getClassOtherInfo 类的包名:package com.java.reflect.demo 类的父类:com.java.reflect.demo.Creature 类的接口: interfaces[0] :interface com.java.reflect.demo.ISpeakLister interfaces[1] :interface java.io.Serializable 类的所有内部类 ,包括private: innerClass1[0] :class com.java.reflect.demo.Person$innerClass innerClass1[1] :class com.java.reflect.demo.Person$innerPriClass 类的public内部类,包括父类的public内部类: innerClass2[0] :class com.java.reflect.demo.Person$innerClass innerClass2[1] :class com.java.reflect.demo.Creature$InnerCreature ~~~ ### 对类的对象的指定方法,属性,构造方法进行操作 #### 对指定构造方法进行操作 ~~~ //2.3.1 对指定构造方法进行操作 private static void callConstruct(Class c) throws Exception { // TODO Auto-generated method stub System.out.println(" "); System.out.println("callConstruct"); //对private类型的构造方法进行操作 Constructor constructor1 = c.getDeclaredConstructor(String.class); constructor1.setAccessible(true); person = (Person)constructor1.newInstance("zsmj"); System.out.println("person:"+person); //对public类型的构造方法进行操作 Constructor constructor2 = c.getDeclaredConstructor(String.class,int.class,int.class); //constructor2.setAccessible(true); person = (Person)constructor2.newInstance("yyf",10,2); System.out.println("person:"+person); } ~~~ 输出信息: ~~~ callConstruct person:Persion [name=zsmj, age=0, id=0,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] Person--Person(String name,int age,int id) person:Persion [name=yyf, age=10, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] ~~~ #### 对指定方法进行操作 ~~~ //2.3.2 对指定方法进行操作 private static void callMethod(Class c) throws Exception { // TODO Auto-generated method stub System.out.println(" "); System.out.println("callMethod"); //1.对private类型的方法进行操作 //getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法 System.out.println("getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以setName方法为例:"); Method m1 = c.getDeclaredMethod("setName", String.class); m1.setAccessible(true); System.out.println("修改前的person:"+person); m1.invoke(person, "yyf_01"); System.out.println("修改后的person:"+person); //2.对public类型的方法进行操作,包括父类的方法 //getMethod 对public类型的方法进行操作,包括父类的方法 //2.1 以运行类的本身声明的public类型的setAge方法为例 System.out.println("getMethod 对public类型的方法进行操作,包括父类的方法,以类本身的setAge方法为例:"); Method m2 = c.getMethod("setAge", int.class); System.out.println("修改前的person:"+person); m2.invoke(person, 11); System.out.println("修改后的person:"+person); //2.2 以运行类的父类声明的public类型的setWeight方法为例 System.out.println("getMethod 对public类型的方法进行操作,包括父类的方法,以父类的setWeight方法为例:"); Method m3 = c.getMethod("setWeight", int.class); System.out.println("修改前的person:"+person); m3.invoke(person, 100); System.out.println("修改后的person:"+person); //3.对static类型的方法进行操作,以类本身的showWeather静态方法为例 System.out.println("getMethod 对public类型的方法进行操作,包括父类的方法,以父类的showWeather方法为例:"); Method m4 = c.getMethod("showWeather"); m4.invoke(null); //4 获取指定方法的返回值,以类本身的private类型的getName方法为例 System.out.println("获取指定方法的返回值,以类本身的private类型的getName方法为例:"); Method m5 = c.getDeclaredMethod("getName"); m5.setAccessible(true); String name = (String)m5.invoke(person); System.out.println("name:"+name); } ~~~ 输出信息: ~~~ callMethod getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以setName方法为例: 修改前的person:Persion [name=yyf, age=10, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] 修改后的person:Persion [name=yyf_01, age=10, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] getMethod 对public类型的方法进行操作,包括父类的方法,以类本身的setAge方法为例: 修改前的person:Persion [name=yyf_01, age=10, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] 修改后的person:Persion [name=yyf_01, age=11, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] getMethod 对public类型的方法进行操作,包括父类的方法,以父类的setWeight方法为例: 修改前的person:Persion [name=yyf_01, age=11, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0] 修改后的person:Persion [name=yyf_01, age=11, id=2,weather=今天天气好晴朗!!]---Creature [weight=100, color=0] getMethod 对public类型的方法进行操作,包括父类的方法,以父类的showWeather方法为例: weather: 今天天气好晴朗!! 获取指定方法的返回值,以类本身的private类型的getName方法为例: name:yyf_01 ~~~ #### 对指定属性进行操作 ~~~ //2.3.3 对指定属性进行操作 private static void callField(Class c) throws Exception { // TODO Auto-generated method stub System.out.println(" "); System.out.println("callField"); //1.对public类型的属性进行操作,以类本身的public属性id为例: System.out.println("对public类型的属性进行操作,以类本身的public属性id为例"); Field f1 = c.getField("id"); int id = (int)f1.get(person); System.out.println("修改前person对象的id="+id); f1.set(person, 3); id = (int)f1.get(person); System.out.println("修改后person对象的id="+id); //2.对private类型的属性进行操作,以类本身的private属性age为例: System.out.println("对private类型的属性进行操作,以类本身的private属性age为例:"); Field f2 = c.getDeclaredField("age"); f2.setAccessible(true); int age = (int)f2.get(person); System.out.println("修改前person对象的age="+age); f2.set(person, 12); age = (int)f2.get(person); System.out.println("修改后person对象的age="+age); //3.对static类型的属性进行操作,以类本身的static属性weather为例: System.out.println("对static类型的属性进行操作,以类本身的static属性weather为例:"); Field f3 = c.getDeclaredField("weather"); f3.setAccessible(true); String weather = (String)f3.get(person); System.out.println("修改前person对象的weather="+weather); //f3.set(person, "今天天气好凉爽!!"); f3.set(null, "今天天气好凉爽!!"); weather = (String)f3.get(person); System.out.println("修改后person对象的weather="+weather); } ~~~ 输出信息: ~~~ callField 对public类型的属性进行操作,以类本身的public属性id为例 修改前person对象的id=2 修改后person对象的id=3 对private类型的属性进行操作,以类本身的private属性age为例: 修改前person对象的age=11 修改后person对象的age=12 对static类型的属性进行操作,以类本身的static属性weather为例: 修改前person对象的weather=今天天气好晴朗!! 修改后person对象的weather=今天天气好凉爽!! ~~~ ### 源码下载地址 [http://download.csdn.net/detail/hfreeman2008/9175627](http://download.csdn.net/detail/hfreeman2008/9175627) 参考资料: 1.Java基础核心技术:Java反射机制(day19-day20) [http://edu.csdn.net/course/detail/809](http://edu.csdn.net/course/detail/809)
';

java核心技术之正则表达式

最后更新于:2022-04-01 09:58:34

### 1.正则表达式 正则表达式,又称正规表示法、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE)。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串 ### 2.元字符: | 元字符 | 正则表达式的写法 | 意义 | |-----|-----|-----| | . | “.” | 任意一个字符 | | ^ | “^Spring” | 以Spring开始的字符 | | $ | “EEEE$” | 匹配行结束符,以”EEEE”结束的字符 | | \d | “\d” | 0-9的任何一个数字 | | \D | “\D” | 任何一个非数字字符 | | \s | “\s” | 空白字符,如”\t”,”\n” | | \S | “\S” | 非空白字符 | | \w | “\w” | 可用作标识符的字符,但不包括“$” | | \W | “\W” | 不可用作标识符的字符 | | \p{Lower} | \p{Lower} | 小定字母a-z | | \p{Upper} | \p{Upper} | 大写字母A-Z | | \p{ASCII} | \p{ASCII} | ASCII字符 | | \p{Alpha} | \p{Alpha} | 字母字符 | | \p{Digit} | \p{Digit} | 十进制数字,0-9 | | \p{Alnum} | \p{Alnum} | 数字或字母字符 | | \p{Punct} | \p{Punct} | 标点符号:!“#%&()*=- | | \p{Graph} | \p{Graph} | 可见字符:[\p{Alnum}\p{Punct}] | | \p{Print} | \p{Print} | 可打印字符[\p{Graph}\x20] | | \p{Blank} | \p{Blank} | 空格或制表符:[\t] | | \p{Cntrl} | \p{Cntrl} | 控制字符:[\x00-\x1F\x7F] | ### 3.方括号 方括号括起来若干个字符来表示一个元字符,该元字符可代表方括号中的任何一个字符。 reg=“[abc]4”—– 则”a4”,”b4”,”c4”,都是和此正则表达式匹配的字符串 | 方括号例子 | 意义 | |-----|-----| | [^456] | 代表4,5,6之外的任何字符 | | [a-r] | 代表a~r中的任何一个字母 | | [a-Za-Z] | 代表任意一个英文字母 | | [a-e[g-z]] | 代表a~e或g~z中的任意一个字母 | | [a-o&&[def]] | 代表字母d,e,f(交运算) | | [a-o&&[^bc]] | 代表字母a,d(差运算) | ### 4.()–小括号 将 () 之间括起来的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域,这个元字符在字符串提取的时候非常有用。 ### 5.限定修饰符 使用限定修饰符来限定元字符出现的次数 | 限定修饰符 | 意义 | 示例 | |-----|-----|-----| | ? | 0次或1次 | A? | | * | 0次或多次 | A* | | + | 1次或多次 | A+ | | {n} | 正好出现n次 | A{2} | | {n,} | 至少出现n次 | A{2,} | | {n,m} | 出现n到m次 | A{2,6} | ### 6.几个样例 import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; ~~~ public class Regular { //字符串是否是数字 public static String regexIsDigital = “\d+”; //字符串是否是字母 public static String regexIsAlpha =”\p{Alpha}+”; //字符串是否是15位或18位的身体证号码 public static String regexIsID=”\d{15}|\d{18}”; //字符串是否是JJJ开头KKK结尾 public static String regexIsJJJStartKKKEnd=”^JJJ.*KKK$”; //字符串是否是区号是3或4位数字-(可有可没有)号码任意多少位的数字 public static String regexIsTelePhoneNumber =”[0-9]{3,4}\-?[0-9]+”; //X@X.com.cn public static String regexIsEmail = “\w+@\w+(\.\w{2,3})*\.\w{2,3}”; //字符串是否是汉字 public static String regexIsHanZi=”[\u4e00-\u9fa5]{1,}”; //查找以Java开头,任意结尾的字符串 public static String regexIsStartJava = “^Java.*”; //以多条件分割字符串时 public static String regexSplit =”[, |]+”; ~~~ ~~~ public static void main(String[] args) { testIsDigit(); testIsAlpha(); testIsID(); testStartEnd(); testIsTelePhoneNum(); testEmailAddre(); testIsHanZi(); testIsStartJava(); testSplit(); testReplace(); testPattern(); } private static void testPattern() { Pattern pattern = Pattern.compile(""); System.out.println(pattern.matches("[0-9]{6}", "200038")); System.out.println(pattern.matches("\\d{6}", "200038")); } private static void testReplace() { Pattern pattern = Pattern.compile("正则表达式"); Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World"); //替换第一个符合正则的数据 System.out.println(matcher.replaceFirst("Java")); pattern = Pattern.compile("正则表达式"); matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World"); //替换所有符合正则的数据 System.out.println(matcher.replaceAll("Java")); } private static void testSplit() { Pattern pattern = Pattern.compile(regexSplit); String data = "Java Hello World Java,Hello,,World|Sun"; System.out.println(data+" split by:"+regexSplit); String[] strs = pattern.split(data); for (int i=0;i<strs.length;i++) { System.out.println(strs[i]); } } private static void testIsStartJava() { pressInfoByPattern("Java不是人",regexIsStartJava); pressInfoByPattern("dJava不是人",regexIsStartJava); } private static void testIsHanZi() { pressInfo("验证汉字",regexIsHanZi); } private static void testIsTelePhoneNum() { pressInfo("0733-5544",regexIsTelePhoneNumber); pressInfo("073-566544",regexIsTelePhoneNumber); pressInfo("073566544",regexIsTelePhoneNumber); pressInfo("073--566544",regexIsTelePhoneNumber); } private static void testStartEnd() { pressInfo("JJJKKK",regexIsJJJStartKKKEnd); pressInfo("JJJaaaaKKK",regexIsJJJStartKKKEnd); pressInfo("JJaaaaKKK",regexIsJJJStartKKKEnd); pressInfo("JJJaaaaKK",regexIsJJJStartKKKEnd); } private static void testIsID() { pressInfo("111111111111111",regexIsID); pressInfo("11111111111111",regexIsID); pressInfo("111111111111122221",regexIsID); pressInfo("11111111111112222",regexIsID); } private static void testIsAlpha() { pressInfo("da",regexIsAlpha); pressInfo("d1a",regexIsAlpha); } private static void testIsDigit() { pressInfo("21452",regexIsDigital); pressInfo("21a452",regexIsDigital); pressInfo("021452",regexIsDigital); } private static void testEmailAddre() { pressInfo("aaa@",regexIsEmail); pressInfo("aaaaaaaa",regexIsEmail); pressInfo("11111@11111fffyu.dfg.com",regexIsEmail); } private static void pressInfo(String data,String regex) { if(data.matches(regex)){ System.out.println(data+":is match regex:"+regex); }else{ System.out.println(data+":is not match regex:"+regex); } } private static void pressInfoByPattern(String data,String regex) { Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(data); if(matcher.matches()){ System.out.println(data+":is match regex:"+regex); }else{ System.out.println(data+":is not match regex:"+regex); } } ~~~ } ### 7自己的话 曾经,看到别人能用正则表达式,而自己不会,当时好自卑啊,觉得别人好厉害啊。直到后来,自己坐下来,好好的看了一些正则表达式的资料和例子后,觉得,啊,原来如此。也就是这样,一点都不复杂啊。绝知此事要躬行,古人的话还是有道理的。
';

Java核心技术之基本数据类型

最后更新于:2022-04-01 09:58:32

这篇文章,我们讨论一些java的最基本的东西,这些东西我们一般刚刚学java的时候就学过,但是不一定真正明白。正好,我在做一个读取内存的值,涉及到bit位的值的读取和写。那就可以讨论一个java的基本数据类型的值在机器的详细情况: Java基本数据类型共有八种三类:字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。 Java决定了每种简单类型的大小。这些大小并不随着机器结构的变化而变化。这种大小的不可更改正是Java程序具有很强移植能力的原因之一。 下面,我们就是要分析java基本数据类型的取值范围和占多少字节多少bit(1字节 = 8 bit)。 ### 代码如下: ~~~ public class BaseDataInfo{ public static void main(String[] args) { System.out.println("Boolean.FALSE:"+Boolean.FALSE); System.out.println("Boolean.TRUE:"+Boolean.TRUE); int maxByte = Byte.MAX_VALUE; int minByte = Byte.MIN_VALUE; int sizeByte = Byte.SIZE; System.out.println("Byte.MAX_VALUE:"+maxByte); System.out.println("Byte.MIN_VALUE:"+minByte); System.out.println("Byte.SIZE:"+sizeByte); int maxChar = Character.MAX_VALUE; int minChar = Character.MIN_VALUE; int sizeChar = Character.SIZE; System.out.println("Character.MAX_VALUE:"+maxChar); System.out.println("Character.MIN_VALUE:"+minChar); System.out.println("Character.SIZE:"+sizeChar); int maxShort = Short.MAX_VALUE; int minShort = Short.MIN_VALUE; int sizeShort = Short.SIZE; System.out.println("Short.MAX_VALUE:"+maxShort); System.out.println("Short.MIN_VALUE:"+minShort); System.out.println("Short.SIZE:"+sizeShort); int maxInt = Integer.MAX_VALUE; int minInt = Integer.MIN_VALUE; int sizeInt = Integer.SIZE; int bitCount = Integer.bitCount(10); System.out.println("Integer.MAX_VALUE:"+maxInt); System.out.println("Integer.MIN_VALUE:"+minInt); System.out.println("Integer.SIZE:"+sizeInt); System.out.println("Integer.bitCount(1):"+bitCount); long maxLong = Long.MAX_VALUE; long minLong = Long.MIN_VALUE; int sizeLong = Long.SIZE; System.out.println("Long.MAX_VALUE:"+maxLong); System.out.println("Long.MIN_VALUE:"+minLong); System.out.println("Long.SIZE:"+sizeLong); float maxFloat = Float.MAX_VALUE; float minFloat = Float.MIN_VALUE; int sizeFloat = Float.SIZE; System.out.println("Float.MAX_VALUE:"+maxFloat); System.out.println("Float.MIN_VALUE:"+minFloat); System.out.println("Float.SIZE:"+sizeFloat); Double maxDouble = Double.MAX_VALUE; Double minDouble = Double.MIN_VALUE; int sizeDouble = Double.SIZE; System.out.println("Double.MAX_VALUE:"+maxDouble); System.out.println("Double.MIN_VALUE:"+minDouble); System.out.println("Double.SIZE:"+sizeDouble); } } ~~~ ### 输出结果: Boolean.FALSE:false Boolean.TRUE:true Byte.MAX_VALUE:127 Byte.MIN_VALUE:-128 Byte.SIZE:8 Character.MAX_VALUE:65535 Character.MIN_VALUE:0 Character.SIZE:16 Short.MAX_VALUE:32767 Short.MIN_VALUE:-32768 Short.SIZE:16 Integer.MAX_VALUE:2147483647 Integer.MIN_VALUE:-2147483648 Integer.SIZE:32 Integer.bitCount(1):2 Long.MAX_VALUE:9223372036854775807 Long.MIN_VALUE:-9223372036854775808 Long.SIZE:64 Float.MAX_VALUE:3.4028235E38 Float.MIN_VALUE:1.4E-45 Float.SIZE:32 Double.MAX_VALUE:1.7976931348623157E308 Double.MIN_VALUE:4.9E-324 Double.SIZE:64 ### 从输出结果可以看出: <table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td valign="top"><p>boolean</p></td><td valign="top"><p>只有true和false两个取值</p></td></tr><tr><td valign="top"><p>byte</p></td><td valign="top"><p>8位,最大存储数据量是255,存放的数据范围是-128~127之间</p></td></tr><tr><td valign="top"><p>short</p></td><td valign="top"><p>16位,最大数据存储量是65536,数据范围是-32768~32767之间</p></td></tr><tr><td valign="top"><p>int</p></td><td valign="top"><p>32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1(也就是-2147483648~2147483647)。从int取值范围可以看,int适合20亿级别的整形数据。</p></td></tr><tr><td valign="top"><p>long</p></td><td valign="top"><p>64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2 的63次方减1(也就是-9223372036854775808~9223372036854775807)。从long的取值范围可以看出,long适合海量级(亿亿级)的整形数据。</p></td></tr><tr><td valign="top"><p>float</p></td><td valign="top"><p>32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。从float的取值范围可以看出,float适合e38级的float数据。</p></td></tr><tr><td valign="top"><p>double</p></td><td valign="top"><p>64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。从double的取值范围可以看出,double适合e308的double数据。</p></td></tr><tr><td valign="top"><p>char</p></td><td valign="top"><p>16位,存储Unicode码,用单引号赋值</p></td></tr></tbody></table> <table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p align="center">基本数据类型</p></td><td><p align="center">boolean</p></td><td><p align="center">byte</p></td><td><p align="center">char</p></td><td><p align="center">short</p></td><td><p align="center">int</p></td><td><p align="center">long</p></td><td><p align="center">float</p></td><td><p align="center">double</p></td></tr><tr><td><p align="center">bit位数</p></td><td><p align="center">1</p></td><td><p align="center">8</p></td><td><p align="center">16</p></td><td><p align="center">16</p></td><td><p align="center">32</p></td><td><p align="center">64</p></td><td><p align="center">32</p></td><td><p align="center">64</p></td></tr><tr><td><p align="center">字节位数</p></td><td><p align="center">0.125</p></td><td><p align="center">1</p></td><td><p align="center">2</p></td><td><p align="center">2</p></td><td><p align="center">4</p></td><td><p align="center">8</p></td><td><p align="center">4</p></td><td><p align="center">8</p></td></tr><tr><td><p align="center">封装类</p></td><td><p align="center">Boolean</p></td><td><p align="center">Byte</p></td><td><p align="center">Character</p></td><td><p align="center">Short</p></td><td><p align="center">Integer</p></td><td><p align="center">Long</p></td><td><p align="center">Float</p></td><td><p align="center">Double</p></td></tr></tbody></table> ### 参考资料: [Java基本数据类型总结](http://www.cnblogs.com/doit8791/archive/2012/05/25/2517448.html) [http://www.cnblogs.com/doit8791/archive/2012/05/25/2517448.html](http://www.cnblogs.com/doit8791/archive/2012/05/25/2517448.html)
';

Java核心技术之容器

最后更新于:2022-04-01 09:58:30

软件中的数据可以说是非常重要的一部分,而我们组织和操作数据的一般都是java.util包中的一些集合类,这些集合我们称为容器。  ### 一:数组与集合 数组其实也是我们经常用来组织和操作数据的类,但是数组与集合类的不同有二个不同的地方: 1.  数组的长度是固定不变的,集合的长度是可变的。 1.  数组用来存放基本的类型数据,集合用来存放对象的引用。 ### 二:集合      Java容器类包含Collection,  List(链表), ArrayList, LinkedList ,Vector(向量),Stack(堆栈), Set(集合),  TreeSet, HashSet,Map(映射表), TreeMap, HashMap, Queue(队列), Deque(双队列)。 Collection |----List |      |----ArrayList |      |----LinkedList |      |----Vector |              |----Stack |----Set |     |----HashSet |     |----SortedSet |            |----TreeSet |----Queue |     |----Deque Map |----HashMap |----TreeMap #### 2.1 Collection接口 Interface Collection<E>: Collection接口是一个根接口,它提供了对数据的add,remove,iterator()方法。 ~~~ Collection list = new ArrayList(); list.add("a"); list.add("b"); list.add("c"); Iterator it = list.iterator(); while(it.hasNext()){ String str = (String) it.next(); System.out.println(str); } ~~~ #### 2.2  List(链表), ArrayList,LinkedList,Vector,Stack List接口相当于链表,是有序的Collection,其中的元素可重复,各元素的顺序是对象插入的顺序。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。  实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。 Collection |----List            |----LinkedList             |----ArrayList            |----Vector                    |----Stack  ArrayList类: ArrayList实现了可变的数组,允许所有元素,包括null.并可以根据索引位置对集合进行快速的随机访问。缺点是向指定的索引位置插入对象或删除对象的速度较慢。所以,它适合随机查找和遍历,不适合插入和删除。ArrayList是非同步的。 LinkList类: LinkList类采用了链表的结构保存对象。所以便于向集合中插入和删除对象,需要向集合中插入和删除对象时,LinkList类效率较好,但是对于随机访问集合中的对象,LinkList效率慢。所以,它适合数据的动态插入和删除,不适合随机访问和遍历,LinkList也是非同步的。 Vector类: Vector非常类似ArrayList,但是Vector是支持线程同步的。即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。所以,它适合对线程同步有要求的数据,但是效率比ArrayList要慢。 ~~~ Vector vector = new Vector(); vector.addElement("one"); vector.addElement("two"); vector.addElement("three"); vector.insertElementAt("zero",0); vector.insertElementAt("oop",3); vector.setElementAt("three",3); vector.setElementAt("four",4); //vector.removeAllElements(); printData(vector.iterator()); ~~~ ~~~ private static void printData(Iterator it){ while(it.hasNext()){ String str = (String) it.next(); System.out.println(str); } } ~~~ Stack类: Stack是Vector的一个子类,它实现标准的后进先出堆栈。 ~~~ Stack stack = new Stack(); stack.push(new Integer(11111)); printStack(stack); stack.push("absdder"); printStack(stack); stack.push(new Double(29999.3)); printStack(stack); stack.push(220.2); printStack(stack); String s = new String("absdder"); System.out.println("元素absdder在堆栈的位置"+stack.search(s)); System.out.println("元素11111在堆栈的位置"+stack.search(11111)); System.out.println("元素"+stack.pop()+"出栈"); printStack(stack); System.out.println("元素"+stack.pop()+"出栈"); printStack(stack); System.out.println("元素"+stack.pop()+"出栈"); printStack(stack); ~~~ ~~~ private static void printStack(Stack stack) { // TODO Auto-generated method stub if (stack.empty()) System.out.println("堆栈是空的,没有元素"); else { System.out.print("堆栈中的元素:"); Enumeration items = stack.elements(); while (items.hasMoreElements()) System.out.print(items.nextElement()+" "); } System.out.println(); } ~~~ ### 2.3 Set(集合),SortedSet(有序集合),HashSet,TreeSet, Collection |----Set        |----HashSet        |----SortedSet                |----TreeSet Set集合: Set接口,Set集合中的对象不按特定的方式排序,只是简单的把对象加入到集合中,但是Set集合中不能包含重复对象。 SortedSet(有序集合): SortedSet接口扩展了Set并说明了按升序排列的集合的特性  HashSet: HashSet,由哈希表(实际是一个HashMap实例)。它不保证Set的迭代顺序,特别是不保证此顺序不变。 TreeSet: TreeSet类实现了Set和SortedSet接口,因此,能对集合的元素进行排序。 ~~~ Set set = new TreeSet(); set.add("first_item"); set.add("second_item"); set.add("third_item"); Iterator it = set.iterator(); while(it.hasNext()){ String str = (String) it.next(); System.out.println(str); } ~~~ ### 2.4 Map,HashMap,TreeMap |----Map |     |----HashMap |     |----TreeMap Map: Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个 value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。 HashMap: HashMap类实现了Map集合,是基于哈希表的Map接口实现,允许使用null值和null键。它实现的Map集合对于添加和删除映射关系效率比较高,所以用的比较多。但是HashMap不能保证映射的顺序。 TreeMap: TreeMap类实现了Map和SortedMap接口,因此映射的关系有一定的顺序,但是添加,删除和定位映射关系时,性能比HashMap差。由于TreeMap映射有一定的顺序,所以不允许键对象是null。 ~~~ HashMap hashmap = new HashMap(); hashmap.put("key_Item0","Value0"); hashmap.put("key_Item1","Value1"); hashmap.put("key_Item2","Value2"); hashmap.put("key_Item3","Value3"); Set set = hashmap.entrySet(); Iterator iterator = set.iterator(); while(iterator.hasNext()) { Map.Entry mapentry = (Map.Entry) iterator.next(); System.out.println(mapentry.getKey()+"/"+mapentry.getValue()); } set = hashmap.keySet(); Iterator it = set.iterator(); while(it.hasNext()){ String str = (String) it.next(); System.out.println(str); } Collection collection = hashmap.values(); it = collection.iterator(); while(it.hasNext()){ String str = (String) it.next(); System.out.println(str); } ~~~ ### 2.5 queue(队列), Deque(双队列) |----Collection |     |----Queue |     |----Deque queue(队列): 队列是一种数据结构.它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个元素就是说,队列以一种先进先出的方式管理数据。 ~~~ Queue<String> queue = new LinkedList<String>(); //添加元素 queue.offer("a"); queue.offer("b"); queue.offer("c"); queue.offer("d"); queue.offer("e"); for(String q : queue){ System.out.println(q); } System.out.println("==="); System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除 for(String q : queue){ System.out.println(q); } System.out.println("==="); System.out.println("element="+queue.element()); //返回第一个元素 for(String q : queue){ System.out.println(q); } System.out.println("==="); System.out.println("peek="+queue.peek()); //返回第一个元素 for(String q : queue){ System.out.println(q); } ~~~ Deque(双队列): Deque(双队列),或双端队列,是需要在队列的二端都能插入和删除数据,但是不需要在中队列的中间插入和删除数据的场合所使用的一种数据结构。 ### 三.参考资料: (1)Java 从入门到精通 第二版 清华大学出版社 李钟尉,周小彤编著 第14章 集合类 (2)java api [http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4](http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4) (3)Java容器——JSTL学习笔记 [http://www.cnblogs.com/viviman/archive/2013/01/14/2860198.html](http://www.cnblogs.com/viviman/archive/2013/01/14/2860198.html) (4)Java容器集合类的区别用法 [http://www.cnblogs.com/sunliming/archive/2011/04/05/2005957.html](http://www.cnblogs.com/sunliming/archive/2011/04/05/2005957.html) (5)游戏编程精粹1 1.4 在游戏编程中使用STL
';

Java核心技术之Comparator和Comparable在排序中的应用

最后更新于:2022-04-01 09:58:27

### 自定义的类User: ~~~ package com.example.testcomparator; public class User{ private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } 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 String toString(){ return "name:"+name+"--age:"+age; } } ~~~ 当我们有一组User对象组合时,我们要对其中的User对象排序,优先对name排序,如果name一样,则再依据age排序。 ### 1.使用Comparator接口来排序: ~~~ package com.example.testcomparator; import java.util.Comparator; //先比较id,再比较age public class UserComparator implements Comparator<User>{ @Override public int compare(User user0, User user1) { // TODO Auto-generated method stub int flag = 0; flag = user0.getName().compareTo(user1.getName()); if(flag == 0) { // 如果id一样,比较年龄, 返回比较年龄结果 return user0.getAge() - user1.getAge(); } else { return flag; // 名字不一样, 返回比较id的结果. } } } ~~~ 排序方法,我们分别对List和数组来分别排序: (1)List排序: ~~~ List userList = new ArrayList<User>(); userList.add(new User("a",5)); userList.add(new User("c",6)); userList.add(new User("a",4)); userList.add(new User("b",2)); userList.add(new User("b",3)); userList.add(new User("c",7)); for(int i = 0;i<userList.size();i++){ Log.i(TAG, "排序前:"+userList.get(i)); } Collections.sort(userList, new UserComparator()); for(int i = 0;i<userList.size();i++){ Log.i(TAG, "排序后:"+userList.get(i)); } ~~~ (2)对数组排序: ~~~ User[] userArray = new User[]{ new User("a", 5), new User("c", 6), new User("a", 4), new User("b", 2), new User("b", 3), new User("c", 7)}; for(int i = 0;i<userArray.length;i++){ Log.i(TAG, "排序前:"+userArray[i]); } Arrays.sort(userArray,new UserComparator()); for(int i = 0;i<userArray.length;i++){ Log.i(TAG, "排序后:"+userArray[i]); } ~~~ 输出结果: 排序前:name:a--age:5 排序前:name:c--age:6 排序前:name:a--age:4 排序前:name:b--age:2 排序前:name:b--age:3 排序前:name:c--age:7 排序后:name:a--age:4 排序后:name:a--age:5 排序后:name:b--age:2 排序后:name:b--age:3 排序后:name:c--age:6 排序后:name:c--age:7 ### 2.使用Comparable接口来排序: 先要改造User类: ~~~ package com.example.testcomparator; public class User implements Comparable<Object>{ private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } 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 String toString(){ return "name:"+name+"--age:"+age; } @Override //先比较id,id相同后再比较age public int compareTo(Object object) { // TODO Auto-generated method stub int flag = 0; flag = name.compareTo(((User)object).getName()); // 使用字符串的比较 if(flag == 0) { // 如果id一样,比较年龄, 返回比较年龄结果 return age - ((User)object).getAge(); } else { return flag; // 名字不一样, 返回比较id的结果. } } } ~~~ (1)List排序: ~~~ List userList = new ArrayList<User>(); userList.add(new User("a",5)); userList.add(new User("c",6)); userList.add(new User("a",4)); userList.add(new User("b",2)); userList.add(new User("b",3)); userList.add(new User("c",7)); for(int i = 0;i<userList.size();i++){ Log.i(TAG, "排序前:"+userList.get(i)); } Collections.sort(userList); for(int i = 0;i<userList.size();i++){ Log.i(TAG, "排序后:"+userList.get(i)); } ~~~ (2)对数组排序: ~~~ User[] userArray = new User[]{ new User("a", 5), new User("c", 6), new User("a", 4), new User("b", 2), new User("b", 3), new User("c", 7)}; for(int i = 0;i<userArray.length;i++){ Log.i(TAG, "排序前:"+userArray[i]); } Arrays.sort(userArray); for(int i = 0;i<userArray.length;i++){ Log.i(TAG, "排序后:"+userArray[i]); } ~~~ 输出结果: 排序前:name:a--age:5 排序前:name:c--age:6 排序前:name:a--age:4 排序前:name:b--age:2 排序前:name:b--age:3 排序前:name:c--age:7 排序后:name:a--age:4 排序后:name:a--age:5 排序后:name:b--age:2 排序后:name:b--age:3 排序后:name:c--age:6 排序后:name:c--age:7 ### 3.总结: comparable   Comparator 都是用来实现集合中的排序的。 Comparable是在集合内部定义的方法实现的排序, Comparator是在集合外部实现的排序, 所以,如想实现排序,就需要在集合外定义Comparator接口的方法compare()或在集合内实现Comparable接口的方法compareTo()。 两种方法各有优劣:  用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了,  并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。 用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为,所以,我们推荐使用Comparator. ### 4.参考资料: 1.Comparator和Comparable在排序中的应用 [http://www.blogjava.net/fastunit/archive/2008/04/08/191533.html](http://www.blogjava.net/fastunit/archive/2008/04/08/191533.html) 2.Java中,如果想要排序,实现Comparator接口 //与Comparable 的区别? [http://zhidao.baidu.com/link?url=54BbyjAWPv5pG3l9c_ww0-4vPPdQSZ6FZ6u-yJAh52bJwXRRyTPN9iUUvpUYzKOMBLhl80Po2qfBI4Vipansh_](http://zhidao.baidu.com/link?url=54BbyjAWPv5pG3l9c_ww0-4vPPdQSZ6FZ6u-yJAh52bJwXRRyTPN9iUUvpUYzKOMBLhl80Po2qfBI4Vipansh_)
';

前言

最后更新于:2022-04-01 09:58:25

> 原文出处:[java核心技术](http://blog.csdn.net/column/details/java-key-core-points.html) > 作者:[hfreeman2008](http://blog.csdn.net/hfreeman2008) **本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!** # java核心技术 > 通过自己的开发经验,重点讲解java语言中的一些核心关键的,但是理解有一点难度的技术。比如:基本数据类型,容器,正则表达式,反射,IO流,等等!
';