我在一些C#的帖子中看到了“using”关键字的提及。Java是否有相当的语法结构?
是的。Java 1.7引入了try-with-resources结构,使您可以编写:
try(InputStream is1 = new FileInputStream("/tmp/foo");
InputStream is2 = new FileInputStream("/tmp/bar")) {
/* do stuff with is1 and is2 */
}
...就像using
语句一样。
不幸的是,在Java 1.7之前,Java程序员被迫使用try{ ... } finally { ... }。在Java 1.6中:
InputStream is1 = new FileInputStream("/tmp/foo");
try{
InputStream is2 = new FileInputStream("/tmp/bar");
try{
/* do stuff with is1 and is 2 */
} finally {
is2.close();
}
} finally {
is1.close();
}
是的,自Java 7以来,您可以重写:
InputStream is1 = new FileInputStream("/tmp/foo");
try{
InputStream is2 = new FileInputStream("/tmp/bar");
try{
/* do stuff with is1 and is2 */
} finally {
is2.close();
}
} finally {
is1.close();
}
As
try(InputStream is1 = new FileInputStream("/tmp/foo");
InputStream is2 = new FileInputStream("/tmp/bar")) {
/* do stuff with is1 and is2 */
}
try语句中的参数对象应该实现java.lang.AutoCloseable
接口。请查看官方文档。
using (InputStream in as FileInputStream("myfile")) {
... use in ...
}
变成
final InputStream in = FileInputStream("myfile");
try {
... use in ...
} finally {
in.close();
}
acquire;
try {
use;
} finally {
release;
}
如果获取操作在try块中,当获取失败时您将会进行释放。在某些情况下,您可能可以通过不必要的代码(通常是在上面的示例中测试null)来解决问题,但是在ReentrantLock的情况下,会发生糟糕的事情。
如果您经常执行相同的操作,可以使用“执行周围”习语。不幸的是,Java的语法很冗长,因此有很多样板文件。
fileInput("myfile", new FileInput<Void>() {
public Void read(InputStream in) throws IOException {
... use in ...
return null;
}
});
在哪里
public static <T> T fileInput(FileInput<T> handler) throws IOException {
final InputStream in = FileInputStream("myfile");
try {
handler.read(in);
} finally {
in.close();
}
}
更复杂的例子是,例如,包装异常。
据我所知,不行。你可以用try...finally块来进行某种程度上的模拟,但仍然不完全相同。
在Java中,最接近的方法是使用try/finally。此外,Java没有提供隐式的Disposable类型。
C#:将变量作用域限制在using块之外
public class X : System.IDisposable {
public void Dispose() {
System.Console.WriteLine("dispose");
}
private static void Demo() {
X x = new X();
using(x) {
int i = 1;
i = i/0;
}
}
public static void Main(System.String[] args) {
try {
Demo();
} catch (System.DivideByZeroException) {}
}
}
Java:在块外范围变量的作用域
public class X {
public void dispose() {
System.out.println("dispose");
}
private static void demo() {
X x = new X();
try {
int i = 1 / 0;
} finally {
x.dispose();
}
}
public static void main(String[] args) {
try {
demo();
} catch(ArithmeticException e) {}
}
}
C#: 在块内限定变量的范围
public class X : System.IDisposable {
public void Dispose() {
System.Console.WriteLine("dispose");
}
private static void Demo() {
using(X x = new X()) {
int i = 1;
i = i/0;
}
}
public static void Main(System.String[] args) {
try {
Demo();
} catch (System.DivideByZeroException) {}
}
}
Java: 在代码块中限定变量的作用域
public class X {
public void dispose() {
System.out.println("dispose");
}
private static void demo() {
{
X x = new X();
try {
int i = 1 / 0;
} finally {
x.dispose();
}
}
}
public static void main(String[] args) {
try {
demo();
} catch(ArithmeticException e) {}
}
}
我认为你可以通过实现一个匿名内部类来实现类似于“using”块的功能。就像Spring在“Dao Templates”中所做的那样。
嗯,使用它只是语法糖,所以Java的同行们,不要担心。
withLock(lock) { //closure }
大多数程序员在第一个示例中使用的惯用语是:
InputStream is1 = null;
InputStream is2 = null;
try{
is1 = new FileInputStream("/tmp/bar");
is2 = new FileInputStream("/tmp/foo");
/* do stuff with is1 and is 2 */
} finally {
if (is1 != null) {
is1.close();
}
if (is2 != null) {
is2.close();
}
}
使用这种惯用语法,缩进会减少,当你需要清理超过两个资源时,这一点变得更加重要。
此外,你可以向结构体中添加一个 catch 子句,以处理新的 FileStream() 抛出异常的情况,如果需要的话。在第一个示例中,如果您想要执行此操作,则必须有另一个封闭的 try/catch 块。