问题出现时,你也许不清楚改如何处理,但是你应该知道不应该置之不理。建议的做法是看看是不是别人在别的地方处理过类似问题,参考他们的做法并尝试去解决问题
Java的基本概念是“结构不佳的代码不能运行”, 错误恢复在我们所编写的每个程序中都是基本要素,在Java中Throwable被用来表示任何可以作为异常被抛出的类,Throwable对象可分为两种类型,Error用来表示编译时和系统错误,Exception是可以被抛出的基本类
Throwable对象是异常类型的根类。通常对于不同类型的错误要抛出相应的异常。错误信息保存在异常对象的内部或者用异常类的名称来暗示。上一层环境捕获异常,然后通过这些信息来决定如何处理
理解异常是如何被捕获的,必须先要理解监控区域(guarded region)的概念,它是一段可能产生异常的代码,并且后面跟着处理异常的代码
try..catch块主要用于处理异常, 一般会将可能出现问题的代码写在try块中,以处理程序中出现的程序错误,如果一个异常发生在try块中,如果异常需要被相应的程序处理,那么就使用catch块来捕获异常,并在catch块中填写处理异常的代码,就像下面的方式
try {
//这里是可能出现问题的代码
}catch(Exception e){
//捕获后处理的代码
}
举个例子
实现从配置文件system.properties配置文件中读取配置项system.info的配置信息(参考代码如下)
###system.properties文件配置
system.info=This is a try..catch tesing
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ResourceClose6Test {
public static void main(String[] args) throws IOException {
String fileName = "system.properties";
Properties p = new Properties();
InputStream inputStream= ResourceClose6Test.class.getClassLoader().getResourceAsStream(fileName);
p.load(inputStream);
System.out.println(p.get("system.info"));//结果:This is a try..catch tesing
}
}
读取过程中可能存在异常.比如当配置文件地址或者名称不正确,找不到的时候inputStream 对象为空,使用Properties#load 方法就会出现空指针错误
Exception in thread "main" java.lang.NullPointerException
at com.java6.ResourceClose6Test.main(ResourceClose6Test.java:19)
因此,将可能出现问题的代码放入try...catch块,将出错代码放入try块中,异常处理代码放入catch块中,大致代码如下
public class ResourceClose6Test {
public static void main(String[] args) throws IOException {
String fileName = "system.properties";
InputStream inputStream = null;
Properties p = new Properties();
try {
inputStream = ResourceClose6Test.class.getClassLoader().getResourceAsStream(fileName);
p.load(inputStream);
} catch (Exception e) {
//Exception异常处理
}
System.out.println(p.get("system.info"));
}
}
异常处理可以通过一个或者多个catch块来处理程序异常,每个catch块是一个异常处理程序。它的接收参数是一个异常类型,异常类型也表示对应的处理程序块可以处理的那个异常类(同时也会处理参数异常的子类异常)。
public class ResourceClose6Test {
public static void main(String[] args) throws IOException {
String fileName = "system.properties";
InputStream inputStream = null;
Properties p = new Properties();
try {
inputStream = ResourceClose6Test.class.getClassLoader().getResourceAsStream(fileName);
p.load(inputStream);
} catch (IOException e) {
//IOException异常处理
} catch (Exception e) {
//Exception异常处理
}
System.out.println(p.get("system.info"));
}
}
对于一些代码,可能会希望无论try块是正确执行还是有异常抛出,它们都能得到执行。 为了达到这个效果,可以在异常处理程序后加上finally子句。一般情况下,要把除内存之外的资源恢复到他们的初始状态时,就会用到finally子句。这种需要清理的资源包括已经打开的文件或者网络连接。以前的工作中,自己写的程序 ftp 连接没有在finally 中关闭,系统中不停消耗资源,就出现了Too Maney Open Files 的异常(Linux : Too many open files 排查方法_=PNZ=BeijingL的博客-CSDN博客)
上述代码中,InputStream对象打开了一个字节流,程序应该在退出之前关闭写流的方法,即执行inputStream#close()方法。为了避免没有关闭引起内存泄露,此方法在发生异常后也需要被执行。此时就可以使用finally块,参考代码如下
public class ResourceClose6Test {
public static void main(String[] args) throws IOException {
String fileName = "system1.properties";
InputStream inputStream = null;
Properties p = new Properties();
try {
inputStream = ResourceClose6Test.class.getClassLoader().getResourceAsStream(fileName);
p.load(inputStream);
} catch (IOException|NullPointerException e) {
throw new RuntimeException("read file error:" + fileName, e);
} finally {
inputStream.close();
}
System.out.println(p.get("system.info"));
}
}
在JAVA7版本中,一个程序也可以捕获多个异常 ,多个异常之间使用“|” 符号拼接到一起,例如一个异常块可以处理IOException 和 NullPointerException 异常
public class ResourceClose6Test {
public static void main(String[] args) throws IOException {
String fileName = "system.properties";
InputStream inputStream = null;
Properties p = new Properties();
try {
inputStream = ResourceClose6Test.class.getClassLoader().getResourceAsStream(fileName);
p.load(inputStream);
} catch (IOException|NullPointerException e) {
//IOException 和 NullPointerException 异常处理
} catch (Exception e) {
//Exception异常处理
}
System.out.println(p.get("system.info"));
}
}
Java7中增加了try-with-resources语句,try-with-resources语句是一种确保资源被关闭的方法, try-with-resources语句是在try使用的时候声明一个或者多个资源, 当try快执行后自动关闭资源,这样做就不用在finally块中手写代码关闭资源。
import java.io.InputStream;
import java.util.Properties;
public class ResourceClose7Test {
public static void main(String[] args) {
String fileName = "system.properties";
Properties p = new Properties();
try (InputStream inputStream = ResourceClose7Test.class.getClassLoader().getResourceAsStream(fileName)) {
p.load(inputStream);
System.out.println(p.get("system.info"));
} catch (Exception e) {
throw new RuntimeException("read file error:" + fileName, e);
}
}
}
那些对象可以使用try-with-resources语法实现自动关闭呢,查看InputStream源码发现其实现了Closeable接口,实现接口Closeable的对象都是可以关闭的数据源或资源的对象。通过调用close方法来释放对象所持有的资源(例如打开的文件)。
//Closeable 接口必须实现close()方法
public interface Closeable extends AutoCloseable {
/**
* 关闭此流并释放所有相关的系统资源
* 1.如果流已经关闭,那么调用方法没有效果
* 2.关闭可能会失败抛出IOException
*/
public void close() throws IOException;
}
Closeable集成了接口AutoCloseable ,AutoCloseable 是1.7版本增加
package java.lang;
/**
* An object that may hold resources (such as file or socket handles)
* until it is closed. The {@link #close()} method of an {@code AutoCloseable}
* object is called automatically when exiting a {@code
* try}-with-resources block for which the object has been declared in
* the resource specification header. This construction ensures prompt
* release, avoiding resource exhaustion exceptions and errors that
* may otherwise occur.
*
* @apiNote
* It is possible, and in fact common, for a base class to
* implement AutoCloseable even though not all of its subclasses or
* instances will hold releasable resources. For code that must operate
* in complete generality, or when it is known that the {@code AutoCloseable}
* instance requires resource release, it is recommended to use {@code
* try}-with-resources constructions. However, when using facilities such as
* {@link java.util.stream.Stream} that support both I/O-based and
* non-I/O-based forms, {@code try}-with-resources blocks are in
* general unnecessary when using non-I/O-based forms.
*
* @author Josh Bloch
* @since 1.7
*/
public interface AutoCloseable {
/**
* 关闭失败抛出Exception异常
*/
void close() throws Exception;
}
通过接口注解可以知道,接口中自动关闭对象close()方法将会在声明了该对象的try with resources块退出时自动被调用执行,另外注解内容中需要注意的是close()方法和 java.io.Closeable接口的close()方法不同,此close() 方法不是幂等的,即多次调用此close方法可能会产生一些明显的副作用。所以如果是先此接口一定要考虑实现的幂等性
try-with-resources 优点
1. 精炼代码
try-with-resources只是帮助我们避免了资源关闭的重复工作,但它并没有代替finally的作用啊,所以1.7后finally仍然是用来处理一定会被执行的代码块
2.代码更完整
在出现资源泄漏的程序中,很多情况是开发人员没有或者开发人员没有正确的关闭资源所导致的。采用try-with-resources的方式,则可以将资源关闭这种与业务实现没有很大直接关系的工作交给JVM完成,省去了部分开发中可能出现的代码风险。
前一篇:Java中java.math.BigInteger用法