Имеет ли java эквивалент предложения С# "using"

Я видел ссылку в некоторых вопросах, связанных с С#, на предложение "using". Имеет ли java эквивалент?

Ответы

Ответ 1

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

Ответ 2

Да, с 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. Посмотрите на официальные документы .

Для более старых версий Java checkout этот ответ и этот ответ.

Ответ 3

Ближайшим эквивалентом в языке является использование try-finally.

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

Более сложный пример my, например, исключений wrap.

Ответ 4

Не то, чтобы я знал. Вы можете несколько имитировать с помощью try... finally block, но это все еще не совсем то же самое.

Ответ 5

Ближе всего вы можете попасть на Java, попробуйте/наконец. Кроме того, Java не предоставляет неявный одноразовый тип.

С#: определение переменной вне используемого блока

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

}

С#: просмотр переменной внутри блока

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

}

Ответ 7

Я думаю, вы можете добиться чего-то похожего на блок "using", реализуя анонимный внутренний класс. Как Spring делает с "Шаблонами Dao".

Ответ 8

Ну, используя синтаксический сахар, так что Java-парни, не потейте.

Ответ 9

Если мы получим закрытия BGGA в Java, это также откроется для подобных структур в Java. Гафтер использовал этот пример в своих слайдах, например:

withLock(lock) { //closure }

Ответ 10

Фактическая идиома, используемая большинством программистов для первого примера, такова:

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

В этой идиоме меньше отступов, что становится еще более важным, когда у вас есть более 2 ресурсов для очистки.

Кроме того, вы можете добавить предложение catch в структуру, которая будет обрабатывать новый FileStream(), бросающий исключение, если вам это нужно. В первом примере вам понадобится еще один закрытый блок try/catch, если вы хотите это сделать.

Ответ 11

Нет. Нет.

Вы можете

public void func(){

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

}

Это дает вам ограниченную область действия предложения, но нет интерфейса IDisposable для вызова кода завершения. Вы можете использовать try {} catch() {} Наконец {}, но у него нет сахара. Кстати, использование финализаторов на Java - это, как правило, плохая идея.

Ответ 12

Нет, в Java нет использования, наиболее похожей функциональностью является ключевое слово "import".