java基础——3——泛型+异常+IO

在Java发布的JDK1.5版本中增加了泛型支持,所谓的泛型就是为了让集合在很大程度上记住元素的数据类型。在没有使用泛型之前,一旦把对象存放进Java集合中,集合只会将元素作为Object对象进行处理。当从集合中取出对象时就需要进行强制类型转换。如果转换错误,则将会引起ClassCastException异常(类型转换异常)。
增加泛型支持后的集合,则可以让集合记住元素的类型,并在编译时检查集合中元素的类型,如果往集合中添加不满足类型要求的对象,编译器则会提示错误。增加泛型后的集合,可以让代码更加简洁,程序更加健壮。
所谓的泛型就是允许在定义类、接口、方法时使用类型形参,这个类型形参将在声明变量、创建对象、调用方法时动态的指定。
在程序中我们为一个ArrayList<String>指定了泛型后,可以把这个ArrayList<String>看成ArrayList的子类,这个类只能存储String类型的元素,但是实际上,系统并没有为ArrayList<String>生成新的class文件,也不会把ArrayList<String>当成新类,因为并不存在这种泛型类。
为了表示各种泛型List的父类,可以使用类型通配符,类型通配符是一个问号?,将一个问号作为类型实参传给List集合,语法格式为:List<?>。这个问号被称为通配符,它的元素类型可以匹配任何类型。
Java的异常机制主要依赖于try、catch、finally、throw和throws五个关键字,其中try关键字后面紧跟着一个花括号括起来的代码块,它里面放置可能会引发异常的代码块。catch后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,多个catch块后面还可以跟一个finally块,用于回收在try块里打开的物理资源,异常机制会保证finally块总会被执行。throws关键字主要在方法签名中使用,用于声明该方法可能抛出的异常;而throw用于抛出一个实际的异常,throw可以单独作为语句使用,抛出一个具体的异常对象。
File是java.io包下代表与平台无关的文件和目录,则程序中操作文件和目录,都可以通过File类来完成。File能新建、删除、重命名文件和目录。File不能访问文件内容本身,如果访问文件内容本身,则需要使用输入/输出流。
File类可以使用文件路径字符串来创建File实例,该文件路径字符串既可以是绝对路径,也可以是相对路径。在默认情况下,系统总是依据用户的工作路径来解释相对路径。
创建File对象后,可以调用File对象的方法来访问。常用的方法如下:
1、访问文件名相关的方法
String getName():返回此文件对象所表示的文件名或路径名。
String getPath():返回此File对象所对应的路径名。
File getAbsoluteFile():返回此File对象所对应的绝对路径指向的File对象。
String getAbsolutePath():返回此File对象所对应的绝对路径。
String getParent():返回此File对象所对应的目录的父目录,以工作路径为准,如果已经在工作路径的根目录下,则返回null,否则返回父目录。
boolean renameTo(File newName):重命名此File对象所对应的文件或目录,成功返回true,否则返回false。
2、文件检测相关的方法
boolean exists():判断File对象所对应的文件或目录是否存在。
boolean canWrite():判断File对象所对应的文件和目录是否可写。
boolean canRead():判断File对象所对应的文件和目录是否可读。
boolean isFile():判断File对象所对应的是否是文件。
boolean isDirectory():判断File对象所对应的是否是目录。
boolean isAbsolute():判断File对象所对应的文件或目录是否绝对路径。例如:如果在Unix/Linux等系统上,如果路径名的开头是/,则表明File对象对应一个绝对路径,在Windows等系统上,如果路径开头是盘符,则说明它是一个绝对路径。
3、获取常规文件信息
long lastModified():返回文件的最后修改时间。
long length():返回文件内容的长度。
4、文件操作相关的方法
boolean createNewFile():当此File对象对应的文件不存在时,创建一个该File对象所对应的文件,创建成功返回true,否则返回false。
boolean delete():删除File对象所在的文件或路径。
5、目录操作相关的方法
boolean mkdir():创建一个File对象所对应的目录,创建的是目录而不是文件。
boolean mkdirs():创建一个File对象所对应的所有目录,如果上级目录不存在,会同时将上级目录创建出来。
File[] listFile():列出File对象的所有子文件和路径,返回File数组。
Static File[] listRoots():列出系统所有根路径。
1、输入流和输出流
按照流向来分,可以分为输入流和输出流
输入流:只能从中读取数据,而不能向其写入数据;基本上是从磁盘文件到系统内存。
输出流:只能向其写入数据,而不能从中读取数据;基本上是从系统内存到磁盘文件。
Java的输入流主要由InputStream和Reader作为基类,而输出流则主要由OutputStream和Writer作为基类。他们都是一些抽象基类,能直接创建实例对象。
2、字节流与字符流
字节流和字符流的用法几乎一样,区别在于字节流和字符流所操作的数据单元不同,字节流操作的数据单元是8位的字节,而字符流操作的数据单元是16位的字符。
字节流主要由InputStreamOutputStream作为基类,字符流主要由Reader和Writer作为基类。
InputStream里包含如下方法:
int read():从输入流中读取单个字节,返回所读取的字节数据。
int read(byte[] b):从输入流中最多读取b.length个字节的数据,并将其存储在字节数组b中,返回实际读取的字节数。
int read(byte[] b,int off,int len):从输入流中最多读取len个字节的数据,并将其存储在数组b中,放入数组b中时,并不是从数组起点开始,而是从off位置开始,返回实际读取的字节数。
Reader里包含如下方法:
int read():从输入流中读取单个字符,返回所读取的字符数据
int read(char[] ch):从输入流中最多读取ch.length个字符的数据,并将其存储在字符数组ch中,返回实际读取的字符数。
int read(char[] ch,int off,int len):从输入流中最多读取len个字符的数据,并将其存储在字符数组ch中,放入数组时,从数组的off位置开始,返回实际读取的字符数。
OutputStreamWriter也非常相似,两个流都提供了如下方法进行输出:
void write(int c):将指定的字节/字符输出到输出流中,其中c既可以表示字节也可以表示字符。
void write(byte[]/char[] buf):将字节数组/字符数组中的数据输出到指定输出流中。
void write(byte[]/char[] buf,int off,int len):将字节数组/字符数组中从off位置开始,长度为len的字节/字符输出到输出流中。
因为字符流直接以字符作为操作单位,所有Writer可以用字符串来代替字符数组,即以String对象作为参数。Writer里还包含了如下两个方法。
void write(String str):将str字符串里包含的字符输出到指定输出流中。
void write(String str,int off,int len):将字符串从off位置开始,长度为len的字符输出到指定输出流中。
输入/输出体系中提供了两个转换流InputStreamReaderOutputStreamWriter,这两个转换流用于实现将字节流转换成字符流,其中InputStreamReader将字节输入流转换成字符输入流,OutputStreamWriter将字节输出流转换成字符输出流.
BufferedReader和java.io.BufferedWriter类各拥有8192字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。如果要在缓冲区中数据未满的情况下将数据写入到目的地,需要使用flush()方法,将数据刷新一下。
PrintStream和PrintWriter
PrintWriter是与字节流相对应的字符流。PrintWriter用于大多数输出,比PrintStream更为合适。建议新开发的代码使用PrintWriter类。 PrintWriter类与PrintStream类的方法是对应的。
ByteArrayInputStream和ByteArrayOutputStream为内存流或者称为数组流。
ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪read()方法要提供的下一个字节。ByteArrayOutputStream类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
ByteArrayInputStream和ByteArrayOutputStream,用于以IO流的方式来完成对字节数组内容的读写,来支持类似内存虚拟文件或者内存映射文件的功能。
DataInputStream和DataOutputStream数据流,用来处理基本数据的IO流。

public static void main(String[] args) throws Exception {
        //创建一个字节流或者内存流,将内容写入到这个流中
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //Date数据流写入的内容被存储在内存流baos中
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeFloat(13.5f);
        dos.writeDouble(12.50);
        dos.writeFloat(14.6f);
        //写完之后可以将baos流包装好进行传输

        //客户端接收到服务器端返回的字节流,进行一次接收,然后进行处理
        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));
        //读取字节流的时候,必须按照写入的方式进行读取,例如:第一个写入了float数据,那么读取的时
//候必须先读取Float,第二写入的是Double,那么读取第二数据的时候必须读入Double。
        System.out.println(dis.readFloat());
        System.out.println(dis.readDouble());
        System.out.println(dis.readFloat());
    }

Object对象流
对象序列化:对象序列化可以将对象保存在磁盘中,或者将对象在网络中进行传输。序列化的机制是可以将对象脱离程序的运行而独立存在。如果让一个类的对象支持序列化机制,则需要让这个类实现Serializable接口就可以了。该接口无须实现任何方法,它只是表明该类的实例是可序列化的。
使用对象流ObjectInputStream和ObjectOutputStream将对象保存到磁盘上或者通过网络进行传输。

public static void main(String[] args) throws Exception {
        //创建一个person对象,此对象已经支持序列化
        Person  person = new Person();
        person.setAge(25);
        person.setName("张三");
        //创建一个Object对象输出流,将此对象写入到文件中去
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("./abc/person.txt")));
        oos.writeObject(person);
        oos.close();
        //创建一个Object对象输入流,将对象从文件中读取出来
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("./abc/person.txt")));
        Person ps = (Person)ois.readObject();
        System.out.println(ps.getName());
        System.out.println(ps.getAge());
    }
举例2:将对象写入到内存流中
    public static void main(String[] args) throws Exception {
        //创建一个person对象,此对象已经支持序列化
        Person  person = new Person();
        person.setAge(25);
        person.setName("张三");
        //创建一个Object对象输出流,将此对象写入到内存流中去
        ByteArrayOutputStream baos =new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(person);

        //创建一个内存输入流,将对象从内存输出流中获取出来
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        //创建一个Object对象输入流,将对象从内存输入中读取出来
        ObjectInputStream ois = new ObjectInputStream(bais);
        Person ps = (Person)ois.readObject();
        System.out.println(ps.getName());
        System.out.println(ps.getAge());
    }

猜你喜欢

转载自blog.csdn.net/qq_39411208/article/details/82182884