第十四章:注释Annotation
基本的Annotation如下5个:@Override、@Deprecated、@SuppressWarnings、@SafeVarargs、@FunctionalInterface。
@Override:限定重写父类方法,它可以强制一个子类必须覆盖父类的方法。@Override主要帮助程序员避免一些低级的错误,能够在后期排查错误起到很好作用。@Override只能修饰方法,不能修饰其它程序元素。
@Deprecated:标记已过时。当其它程序使用已过时的类、方法时,编译器将会发出警告。
@SuppressWarnings:抑制编译器警告。如果修饰类,将会关闭整个类里的编译器警告。
@SafeVarargs:Java7的“堆污染”警告与@SafeVarargs。比如List集合里定义的是String类型,却添加了int类型的元素,编译能通过,运行时将会异常。
@FunctionalInterface:是Java 8 的函数式接口。
@Component为通用注解;@Repository为持久层组件注解;@Service为业务层组件注解;@Scope为Bean的作用于注解;@Autowired、@Inject为指定Bean之间依赖关系的注解;@Value为注入Spring表达式值的注解。
第十五章 输入/输出
1、File类是java.io包下代表与平台无关的文件和目录,不管是文件还是目录都是使用File来操作的,File能新建、删除、重命名文件和目录,File不能访问文件内容本身,如果想访问文件内容本身,请使用输入/输出流。
①访问文件名相关的方法:☞String getName():返回此File对象所代表的文件名或路径名,如果是路径,则返回最后一级子路径名;
☞String getPath():返回此File对象所对应的路径名;
☞File getAbsoluteFile():返回此File对象的绝对路径;
☞String getAbsolutePath():返回此File对象所对应的绝对路径名;
☞String getParent():返回此File对象所对应目录(最后一级子目录)的父目录名;
☞boolean renameTo(File newName):重命名此File对象所对应的文件或目录,返回true或false。
②文件检测相关的方法:☞boolean exists():判断File对象所对应的文件或目录是否存在;
☞boolean canWrite():判断File对象所对应的文件和目录是否可写;
☞boolean canRead()是否可读;
☞boolean isFile():判断是否是文件,而不是目录;
☞boolean isDirectory():判断是否是目录,而不是文件。
③获取常规文件信息:
☞long lastModified():返回文件的最后修改时间;☞long length():返回文件内容的长度。
④文件操作相关的方法:
☞boolean createNewFile():当此File对象不存在时,该方法将新建一个该File对象所指定的文件。☞boolean delete():删除文件或路径。
⑤目录操作相关的方法:
☞boolean mkdir():试图创建一个File对象所对应的目录,如果创建成功,返回true,否则返回false。调用该方法时File对象必须对应一个路径,而不是一个文件。
☞String[] list():列出所有子文件名和路径名,返回String数组;
☞File[] listFiles():列出所有子文件和路径,返回File数组。
Windows的路径分隔符使用反斜杠\,而Java程序中反斜杠代表转义字符,所以需要两个反斜杠,如:F:\\abc\\test.txt,或者直接使用斜线 / 也可以。
理解Java的IO流:
①流的分类:按照流向来分,分为输入流和输出流。数据从内存到硬盘,通常称为输出流,角度都是从程序运行所在的内存来划分的。
②字节流和字符流:字节流的操作单元是8位的字节,字符流操作的数据单元是16位的字符。
Java的IO流的40多个类都是从4个抽象基类派生的:
InputStream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流;
OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流。
InputStream/Reader:是所有输入流的抽象基类,本身不能创建实例,InputStream有3个常用方法:
①int read():从输入流中读取单字节;
②int read(byte[] b):从输入流中最多读取b.length个字节的数据,并将其存储在字节数组中;
③int read(byte[] b,int off,int len)。Reader也有三个常用方法:①int read():从输入流中读取单个字符,,其它与上面类似,只是字节变成字符。
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
抽象基类 | InputStream | OutputStream | Reader | Writer |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
访问字符串 |
|
| StringReader | StringWriter |
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 |
|
| InputStreamReader | OutputStreamWriter |
特殊流 | DataInputStream | DataOutputStream |
|
|
规则:如果进行输入/输出的内容是文本内容,则应该考虑使用字符流;如果内容是二进制内容,考虑字节流。
个人归纳:
①FileInputStream和FileOutputStream:一般读字节流文件,如图片,音频;
②FileReader和FileWriter:一般读字符流文件,如文本文件;
③Object OutputStream和FileOutputStream结合使用,把序列化对象读出;
④DataInputStream类从数据输入流中读取基本数据,可使用数据输出流写入稍后由数据输入流读取数据;
⑤BufferedReader从字符输入流读取文体,缓冲各个字符,与FileReader结合读取;
⑥File开头的字符、字节流都可以单独使用,必须与数组配合,且都有对应的缓冲流;处理中文且使用字节流,会出现数组长度不够造成乱码情况;
例子:
1(会有乱码)、
FileInputStream inputStream = new FileInputStream("D:\\这是测试Java的文件夹\\myTest1.txt");
byte[] bbuf = new byte[100];// 创建的数组如果小了,会导致中文乱码
int hasRead = 0;
while ((hasRead = inputStream.read(bbuf)) > 0) {
System.out.println(new String(bbuf, 0, hasRead));}
inputStream.close();
2、FileReader fileReader = new FileReader("D:\\这是测试Java的文件夹\\myTest1.txt")// 创建数组char
char[] cbuf = new char[64];
int hasRead = 0;
while ((hasRead = fileReader.read(cbuf)) > 0) {
System.out.println(new String(cbuf, 0, hasRead) + ":得到一行咯");}
3、FileWriter writer = new FileWriter("D:\\这是测试Java的文件夹\\输出来的文件.txt",true);
writer.write("黄鹤楼送孟浩然之广陵——李白\n");
writer.flush();writer.close();
4、两者搭配使用:File f=new File("D:\\这是测试Java的文件夹\\输出来的文件.txt");
BufferedReader reader=new BufferedReader(new FileReader(f));
String nextLine=null;
StringBuffer buffer=new StringBuffer();
nextLine=reader.readLine();
while(nextLine!=null) {buffer.append(nextLine+"\n");
nextLine=reader.readLine();}
对象序列化:对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流。为了让某个类可序列化,该类必须实现两个接口之一:Serializable、Externalizable,Java的很多类已经实现了Srializable,该接口是一个标记接口,实现该接口无须实现任何方法,只是表明该类的实例是可序列化的。一旦某个类实现了Srializable接口,可以通过2个步骤来序列化该对象:
①创建一个ObjectOutputStream,这个输出流是一个处理流:ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("object.txt"));
②调用ObjectOutputStream的writeObject()方法输出可序列化对象:oos.writeObject(per);所保存的文件内容是某个类的对象,打开是乱码。如果希望从二进制流中恢复Java对象,则需要反序列化,步骤如下:
①创建一个ObjectInputStream输入流:
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.txt"));
②调用ObjectInputStream对象的readObject()方法读取流中的对象,该方法返回一个Object类型的Java对象,如果知道该对象的类型,还可以强制转换成其真实的类型:Person p=(Person)ois.readObject();必须指出的是:反序列化读取的仅仅是Java对象的数据,不是Java类,因此必须提供Java对象所属类的class文件,否则异常。反序列化机制无须通过构造器来初始化Java对象。
对于中国的程序员而言,下面几个字符串别名是常用的:
GBK:简体中文字符集;BIG5:繁体中文字符集;ISO-8859-1:ISO拉丁字母表No.1,也叫做ISO-LATIN-1; UTF-8:8位UCS转换格式;UTF-16:16位UCS转换格式。
文件锁:FileChannel cha=new FileOutputStream("a.txt").getChannel();FileLock lock=cha.tryLock();//使用非阻塞方式对指定文件加锁 Thread.sleep(10000);//程序暂停10秒,期间其它程序无法对文件进行修改 lock.release();//释放锁。
Files是一个操作文件的工具类,它提供了大量的便捷方法:
Files.copy(Paths.get("test.txt"),new FileOutputStream("a.txt"));//复制文件
List<String>lines=Files.readAllLines(Paths.get("test.txt"),Charset.forName("gbk"));//一次性读取文件的所有行
FileStore cStore=Files.getFileStore(Paths.get("C:"));
System.out.println("C盘共有空间:"+cStore.getTotalSpace());
System.out.println("C盘可用空间:"+cStore.getUsableSpace());