PrintWriter是具有自动行刷新的缓冲该字符输出流。其提供了比较丰富的构造方法
PrintWriter(File file)
PrintWriter(String fileName)
PrintWriter(OutputStream out)
PrintWriter(OutputStream out,boolean autoFlush)
PrintWriter(Writer writer)
PrintWriter(Writer writer,boolean autoFlush)
其中参数为OutputStream与Writer的构造方法提供了一个可以传入boolean值参数,该参数用于表示PrintWriter是否具有自动行刷新。
1.1.2. PrintWriter的重载print和println方法
使用PrintWriter写出字符串时我们通常不使用Writer提供的write()相关方法,而是使用print和println等方法,PrintWriter提供了若干重载的print与println方法,其中println方法是在写出数据后自动追加一个系统支持的换行符。
重载方法有:
- void print(int i)//打印整数
- void print(char c)//打印字符
- void print(boolean b)//打印boolean值
- void print(char[] c)//打印字符数组
- void print(double d)//打印double值
- void print(float f)//打印float值
- void print(long l)//打印long值
- void print(String str)//打印字符串
注:这些方法还有类似的println方法,参数与上面相同。
FileOutputStream fos = new FileOutputStream("demo.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
//创建带有自动行刷新的PW
PrintWriter pw = new PrintWriter(osw,true);
pw.println("大家好!");
pw.close();
1.2. BufferedReader
1.2.1. 构建BufferedReader对象
BufferedReader是缓冲字符输入流,其内部提供了缓冲区,可以提高读取效率。
BufferedReader的常用构造方法:
- BufferedReader(Reader reader)
例如:
FileInputStream fis = new FileInputStream("demo.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
….
注:因为BufferedReader在构造实例时需要传入一个字符流,所以当我们想基于一个字节流进行读取时,要先将字节流转换为字符流后方可创建缓冲字符输入流BufferedReader。
1.2.2. 使用BR读取字符串
BufferedReader提供了一个可以便于读取一行字符串:
- String readLine()
该方法连续读取一行字符串,直到读取到换行符为止,返回的字符串中不包含该换行符。若EOF则该方法返回null。
例如:
FileInputStream fis = new FileInputStream("demo.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String str = null;
while((str = br.readLine()) != null){
System.out.println(str);
}
br.close();
2. 异常处理
2.1. 异常处理概述
2.1.1. 使用返回值状态标识异常
在JAVA语言出现以前,传统的异常处理方式多采用返回值来标识程序出现的异常情况,这种方式虽然为程序员所熟悉,但却有多个坏处。
首先,一个API可以返回任意的返回值,而这些返回值本身并不能解释该返回值是否代表一个异常情况发生了和该异常的具体情况,需要调用API的程序自己判断并解释返回值的含义。
其次,并没有一种机制来保证异常情况一定会得到处理,调用程序可以简单的忽略该返回值,需要调用API的程序员记住去检测返回值并处理异常情况。这种方式还让程序代码变得冗长,尤其是当进行IO操作等容易出现异常情况的处理时,代码的很大部分用于处理异常情况的switch分支,程序代码的可读性变得很差。
2.1.2. 异常处理机制
当程序中抛出一个异常后,程序从程序中导致异常的代码处跳出,java虚拟机检测寻找和try关键字匹配的处理该异常的catch块,如果找到,将控制权交到catch块中的代码,然后继续往下执行程序,try块中发生异常的代码不会被重新执行。如果没有找到处理该异常的catch块,在所有的finally块代码被执行和当前线程的所属的ThreadGroup的uncaughtException方法被调用后,遇到异常的当前线程被中止。
2.2. 异常的捕获和处理
2.2.1. Throwable,Error和Exception
Java异常结构中定义有Throwable类,Exceotion和Error是其派生的两个子类。其中Exception表示由于网络故障、文件损坏、设备错误、用户输入非法等情况导致的异常,这类异常是可以通过Java异常捕获机制处理的。而Error表示Java运行时环境出现的错误,例如:JVM内存溢出等。
2.2.2. try-catch
try {...} 语句指定了一段代码,该段代码就是一次捕获并处理例外的范围。在执行过程中,该段代码可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句分别对这些异常做相应的处理。
如果没有列外产生,所有的catch代码段都被略过不执行
在catch语句块中是对异常进行处理的代码。catch中声明的异常对( catch(SomeException e) )封装了异常事件发生的信息,在catch语句块中可以使用这个对象的一些方法获取这些信息
常见格式:
...
try{
//可能出现异常的代码片段
}catch(Exception e){
//处理该异常的代码片段
}
...
2.2.3. 多个catch
每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常 。catch捕获的异常类型由上至下的捕获异常类型的顺序应是子类到父类的
例如
- try{
- …
- }catch(NullPointerException e){ //子类异常应在上面捕获
- …
- }catch(RuntimeException e){ //父类异常在下面捕获
- …
- }catch(Exception e){ //应养成最终捕获Exception的习惯
- …
- }
通常在书写代码的时候,我们应当在最后一个catch中捕获Exception,这样可以保证代码不会因为出现一个未在catch中声明的异常而导致捕获失败使得程序终止。
finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序其它部分以前,能够对程序的状态作统一管理。
无论try所指定的程序块中是否抛出例外,finally所指定的代码都要被执行,通常在finally语句中可以进行资源的消除工作,如关闭打开的文件、删除临时文件等。
finally语句块只能定义在try语句块之后,或者最后一个catch语句块之后,且只能定义一次。
当程序发生错误而无法处理的时候,会抛出对应的异常对象,除此之外,在某些时刻,您可能会想要自行抛出异常,例如在异常处理结束后,再将异常抛出,让下一层异常处理区块来捕捉,若想要自行抛出异常,您可以使用“throw”关键词,并生成指定的异常对象。
例如:
throw new ArithmeticException();
2.2.6. throws关键字
程序中会声明许多方法(Method),这些方法中可能会因某些错误而引发异常,但您不希望直接在这个方法中处理这些异常,而希望调用这个它的方法来统一处理,这时候您可以使用“throws”关键词来声明这个方法将会抛出异常
例如:
- public static void stringToDate(String str) throws ParseException{ ……
- }
当使用继承时,在父类的某个方法上声明了throws抛出某些异常,而在子类中重写该方法时,我们可以做以下的操作:
但是不能做以下操作:
Java异常可以分为可检测异常,非检测异常
可检测异常:可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或声明规则,不捕捉这个异常,编译器就通不过,不允许编译
非检测异常:非检测异常不遵循处理或者声明规则。在产生此类异常时,不一定非要采取任何适当操作,编译器不会检查是否已经解决了这样一个异常
RuntimeException 类属于非检测异常,因为普通JVM操作引起的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在java应用程序中会频繁出现。因此它们不受编译器检查与处理或声明规则的限制 。
IllegalArgumentException
抛出的异常表明向方法传递了一个不合法或不正确的参数
NullPointerException
当应用程序试图在需要对象的地方使用 null 时,抛出该异常
ArrayIndexOutOfBoundsException
当使用的数组下标超出数组允许范围时,抛出该异常
ClassCastException
当试图将对象强制转换为不是实例的子类时,抛出该异常
NumberFormatException
当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
Throwable中定义了一个方法可以输出错误信息,用来跟踪异常事件发生时执行堆栈的内容。该方法定义为:
void printStackTrace()
例如:
try{
…
}catch(Exception e){
e.printStackTrace();//输出执行堆栈信息
}
2.4.2. getMessage
Throwable中定义了一个方法可以得到有关异常事件的信息。该方法定义为:
String getMessage()
String getMessage()
例如:
try{
…
}catch(Exception e){
System.out.println(e.getMessage());
}
try{
…
}catch(Exception e){
System.out.println(e.getMessage());
}
很多时候,当一个异常由另一个异常导致异常而被抛出的时候,Java库和开放源代码会将一种异常包装成另一种异常。这时,日志记录和打印根异常就变得非常重要。Java异常类提供了 getCause()方法来检索导致异常的原因,这些可以对异常根层次的原因提供更多的信息。该Java实践对代码的调试或故障排除有很大的帮助。另外,如果要把一个异常包装成另一种异常,构造一个新异常就要传递源异常。
Throwable getCause()
Throwable getCause()
获取该异常出现的原因。
Java异常机制可以保证程序更安全和更健壮。虽然Java类库已经提供很多可以直接处理异常的类,但是有时候为了更加精准地捕获和处理异常以呈现更好的用户体验,需要开发者自定义异常。
创建自定义异常类,语法格式:
public class [自定义异常类名] extends Exception{
…
}
public class [自定义异常类名] extends Exception{
…
}
当定义好自定义异常后,我们可以通过Eclipse来自动生成相应的构造方法。
具体步骤如下:
例如:
public class MyException extends Exception{
public MyException() {
super();
// TODO Auto-generated constructor stub
}
public MyException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public MyException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public MyException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}