tags:

views:

880

answers:

11

I've seen reference in some C# posted questions to a "using" clause. Does java have the equivalent?

+15  A: 

No, Java programmers are forced to use try{ ... } finally { ... } which is sad (though I suppose, try-finally is kind of equivalent, though it does not provide scoping the way using does).

In Java:

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();
}

As you can see the nesting gets out of control quite quickly; however, in C# (as I understand it), you can write something similar to this (excuse the java class names):

using(InputStream is1 as new FileInputStream("/tmp/foo")){
    using(InputStream is2 as new FileInputStream("/tmp/bar")){
        /* do stuff with s1 and s2 */
    }
}
Aaron Maenpaa
Is it possible to update this answer with an example of C# with its using block, then Java with a try-finally? Preferably an example that uses 2 separate resources so we can document how to make sure everything is closed properly.
Outlaw Programmer
As a Java guy, the comparison above is just kind of painful.
Aaron Maenpaa
Although technically correct, this try/finally pattern is not the best. Use: X x = new X(); try{ /*work*/ } finally { x.dispose(); }
McDowell
Unless of course new X() throws exceptions, such as a FileNotFoundException, at which point you have to either introduce another level of try-except, or use the above and handle the FileNotFoundException using the existing try. Neither option is particularly palatable.
Aaron Maenpaa
There is no catch block. If "new X()" throws an exception, nothing will be allocated to "X x", so there is no need to check if it is null. You will never reach finally.
McDowell
McDowell is right. If your allocations throw, then there's nothing to do in the finally block. You realize this. You just don't realize that you realize it. :) Your checks for null are to work around the fact that your allocations are in the wrong location.
Derek Park
In retrospect, I agree with separating handling of the FNF exception from ensuring the stream gets closed. Even if it requires yet another outer try... catch block or a throws declaration.
Aaron Maenpaa
This code won't even compile now. Anything used in the finally block has to have been declared outside the try block.
Michael Myers
+2  A: 

Not that I'm aware of. You can somewhat simulate with a try...finally block, but it's still not quite the same.

Bob King
A: 

No, there is no using in Java, the most similar functionality is the "import" keyword.

The original poster was not referring to includes. See http://msdn.microsoft.com/en-us/library/yh598w02(VS.80).aspx
McDowell
Poor @shifoz! You guys are cruel. The question was totally vague and he could've meant this http://msdn.microsoft.com/en-us/library/sf0df423(VS.80).aspx... Shifoz, you can recover some points by asking something about programmers like "what's your fav programming color in RGB?"
Yar
A: 

No there isn't.

You can

public void func(){

  {
    ArrayList l  =  new ArrayList();
  }
  System.out.println("Hello");

}

This gives you the limited scope of the using clause, but there isn't any IDisposable interface to call finalization code. You can use try{}catch(){}Finally{}, but it doesn't have the sugar of using. Incidentally using finalizers in Java is generally a bad idea.

Steve g
A: 

I think you can achieve something similar to the "using" block, implementing an anonymous inner class. Like Spring does with the "Dao Templates".

Pablo Fernandez
+1  A: 

The closest you can get in Java is try/finally. Also, Java does not provide an implicit Disposable type.

C#: scoping the variable outside a using block

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: scoping the variable outside a block

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#: scoping the variable inside a block

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: scoping the variable inside a block

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) {}
    }

}
McDowell
+4  A: 

This is being talked about for Java 7: Automatic Resource Management

Alan Moore
+1  A: 

Well, using was syntactic sugar anyway so Java fellows, don't sweat it.

Andrei Rinea
+4  A: 

The nearest equivalent within the language is to use try-finally.

using (InputStream in as FileInputStream("myfile")) {
    ... use in ...
}

becomes

final InputStream in = FileInputStream("myfile");
try {
    ... use in ...
} finally {
    in.close();
}

Note the general form is always:

acquire;
try {
    use;
} finally {
    release;
}

If acquisition is within the try block, you will release in the case that the acquisition fails. In some cases you might be able to hack around with unnecessary code (typically testing for null in the above example), but in the case of, say, ReentrantLock bad things will happen.

If you're doing the same thing often, you can use the "execute around" idiom. Unfortunately Java's syntax is verbose, so there is a lot of bolier plate.

fileInput("myfile", new FileInput<Void>() {
   public Void read(InputStream in) throws IOException {
       ... use in ...
       return null;
   }
});

where

public static <T> T fileInput(FileInput<T> handler) throws IOException {
    final InputStream in = FileInputStream("myfile");
    try {
        handler.read(in);
    } finally {
        in.close();
    }
}

More complicated example my, for instance, wrap exceptions.

Tom Hawtin - tackline
A: 

If we get BGGA closures in Java, this would also open up for similar structures in Java. Gafter has used this example in his slides, for example:

withLock(lock) { //closure }
Lars Westergren
+1  A: 

The actual idiom used by most programmers for the first example is this:

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();
    }
}

There is less indenting using this idiom, which becomes even more important when you have more then 2 resources to cleanup.

Also, you can add a catch clause to the structure that will deal with the new FileStream()'s throwing an exception if you need it to. In the first example you would have to have another enclosing try/catch block if you wanted to do this.

This code fails to close is2 if the call to is1.close() throws an exception. The nested code given in the question is preferable.
cunkel