# Java 7 中的`try-with-resources`

> 原文： [https://howtodoinjava.com/java7/try-with-resources/](https://howtodoinjava.com/java7/try-with-resources/)

[**Java 7**](//howtodoinjava.com/category/java-7/ "java 7 features") 为懒惰的 Java 开发人员带来了一些非常好的特性。`try-with-resource`是这样的特性之一，它可以减少代码行，并使代码更健壮。 在本教程中，我将讨论有关此特性的内容。

![java 7 features](img/e9fe6328c61ba53c0ce97bd60ab88afd.png "java 7 features")

```java
Sections in this post: 
The old way of resource cleanup (Before java 7)
The new fancy way with try-with-resources (syntax example)
How actually it works?
Adding functionality to custom resources
Final notes
```

## 资源清除的旧方法（在 Java 7 之前）

我们长期以来一直在这样做。 例如从文件系统读取文件。 代码可能看起来有所不同，但流程如下例所示：

```java
public class ResourceManagementBeforeJava7 
{
	public static void main(String[] args) 
	{
		BufferedReader br = null;
		try 
		{
			String sCurrentLine;
			br = new BufferedReader(new FileReader("C:/temp/test.txt"));
			while ((sCurrentLine = br.readLine()) != null) 
			{
				System.out.println(sCurrentLine);
			}
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		finally 
		{
			try
			{
				if (br != null)
					br.close();
			} 
			catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}
}

```

这些类型的代码在具有大量 IO 操作的应用程序代码库中非常常见。

`try`和`catch`块中的代码本质上很重要，并且具有一些特定于应用程序的逻辑。 但是，`finally`块呢？ 在大多​​数情况下，最后只是复制粘贴了`finally`块，目的是通过关闭它们来避免损坏资源。

当您有 3-4 个这样的资源要在单个`finally`块中关闭时，这些`finally`块看起来更难看。 当我们知道时，您是否认为这些`finally`块不必要地存在，我们必须以任何方式关闭资源而没有任何异常情况？

Java 7 通过`try-with-resources`特性解决了这个问题。

## 使用`try-with-resources`的新方法（语法示例）

现在看看在 Java 7 中打开和关闭资源的新方法。

```java
public class ResourceManagementInJava7 
{
	public static void main(String[] args) 
	{
		try (BufferedReader br = new BufferedReader(new FileReader("C:/temp/test.txt")))
		{
			String sCurrentLine;
			while ((sCurrentLine = br.readLine()) != null) 
			{
				System.out.println(sCurrentLine);
			}
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
	}
}

```

有两件事需要密切注意：

1.  文件资源（`BufferedReader`）以特殊方式在`try`块中打开（在小括号内）。
2.  `finally`块完全消失了。

最后但并非最不重要的一点是，代码看起来很漂亮且易于阅读。 很好，对吗？ 但是实际上是如何工作的？

## 实际上如何运作？

在 Java 7 中，我们有一个新的超接口[**`java.lang.AutoCloseable`**](https://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html "AutoCloseable")。 此接口有一种方法：

```java
void close() throws Exception;

```

Java 文档建议将此接口**实现在不再需要它时必须关闭的任何资源上**。

当我们在特殊的`try-with-resource`块中打开任何此类`AutoCloseable`资源时，在`try`块完成后， **JVM 会对在`try()`块**中初始化的所有资源调用此`close()`方法。

例如，`BufferedReader`已实现`close()`方法文件如下：

```java
public void close() throws IOException {
	synchronized (lock) {
		if (in == null)
			return;
		in.close();
		in = null;
		cb = null;
	}
}

```

由于上述方法定义，当 JVM 调用此方法时，所有基础流或 IO 资源都将关闭。

## 向自定义资源添加功能

好吧，这是一个很好的资源清理设计。 但是它仅适用于 JDK 本机类吗？ 没有。 您也可以将其用于自定义资源。

例如，我在以下代码中创建了一个自定义资源：

```java
public class CustomResource implements AutoCloseable 
{
	public void accessResource() {
		System.out.println("Accessing the resource");
	}

	@Override
	public void close() throws Exception {
		System.out.println("CustomResource closed automatically");
	}
}

```

现在，我将在示例代码中使用它：

```java
public class TryWithCustomResource 
{
	public static void main(String[] args)
	{
		try(CustomResource cr = new CustomResource())
		{
			cr.accessResource();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}

Putput in console:

Accessing the resource
CustomResource closed automatically

```

控制台中的输出清楚地证明，`try`块完成后，资源将自动关闭。

## 最后注意事项

这就是 Java 7 中使用`try-with-resources`进行自动资源管理的全部内容。让我们逐点记下重点：

*   在 Java 7 之前，我们必须使用`finally`块来清理资源。 `finally`块不是强制性的，但是清理资源是为了防止系统损坏。
*   使用 Java 7，无需显式的资源清理。 它是自动完成的。
*   在`try-with-resources`块（`try(…){…}`）中初始化资源时完成自动资源清理。
*   由于新接口`AutoCloseable`而发生清除。 `try`块完成后，JVM 将立即调用其`close`方法。
*   如果要在自定义资源中使用此特性，则必须实现`AutoCloseable`接口。 否则程序将无法编译。
*   您不应在代码中调用`close()`方法。 这应该自动称为 JVM。 手动调用它可能会导致意外结果。

**祝您学习愉快！**