- Есть ли в Java эквивалент C# «using» предложение?
- Ответы 12
- C# vs Java: Using
- Директива / Оператор using
- Импорт типов
- Псевдонимы
- Глобальный импорт через using
- Глобальный импорт через файл проекта
- Импорт статических членов классов
- Wildcard Imports
- Инструкция using и IDisposable
- Как это работает?
- IDisposable Interface
- IAsyncDisposable Interface
- А что там в Java?
- import как аналог using
- Импорт статических членов классов
- Глобальный импорт как c global using
- Wildcard Imports
- try-with-resources
- Как это работает?
- AutoCloseable Interface
- Conclusion
Есть ли в Java эквивалент C# «using» предложение?
Я видел ссылки в некоторых опубликованных на C# вопросах на предложение «using». Есть ли у Java аналог?
с java 7 ответ изменился с нет на да
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше.
Управление транзакциями JDBC — это мощная функция, которая позволяет рассматривать группу операций с базой данных как единую единицу работы. Оно.
WebClient — это реактивный веб-клиент, представленный в Spring 5. Это реактивное, неблокирующее решение, работающее по протоколу HTTP/1.1.
Ответы 12
да. В Java 1.7 появилась конструкция попробовать с ресурсами, позволяющая писать:
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
Можно ли обновить этот ответ примером C# с его блоком using, а затем Java с помощью try-finally? Предпочтительно пример, который использует 2 отдельных ресурса, чтобы мы могли задокументировать, как убедиться, что все закрыто правильно.
Как парню, занимающемуся Java, приведенное выше сравнение довольно болезненно.
Хотя технически правильный, этот шаблон «попробуй / наконец» не самый лучший. Использование: X x = new X (); попробуйте*> finally
Если, конечно, new X () не генерирует исключения, такие как FileNotFoundException, в этот момент вам нужно либо ввести другой уровень try-except, либо использовать вышеуказанное и обработать FileNotFoundException, используя существующую попытку. Ни один из вариантов не особо приятен.
Нет блока захвата. Если «new X ()» вызывает исключение, для «X x» ничего не будет выделено, поэтому нет необходимости проверять, является ли он нулевым. Вы никогда не дойдете до конца.
Макдауэлл прав. Если ваши выделения сбрасываются, то в блоке finally нечего делать. Вы это понимаете. Вы просто не понимаете, что понимаете это. 🙂 Ваши проверки на null должны обойти тот факт, что ваши выделения находятся в неправильном месте.
Оглядываясь назад, я согласен с отделением обработки исключения FNF от обеспечения закрытия потока. Даже если для этого потребуется еще один внешний блок try . catch или объявление throws.
Этот код сейчас даже не компилируется. Все, что используется в блоке finally, должно быть объявлено вне блока try.
Не то, чтобы я в курсе. Вы можете немного смоделировать с помощью блока try . finally, но это все равно не совсем то же самое.
Нет, в Java не используется, наиболее похожая функциональность — ключевое слово import.
Бедный @shifoz! Вы, ребята, жестоки. Вопрос был совершенно расплывчатым, и он мог иметь в виду этот msdn.microsoft.com/en-us/library/sf0df423(VS.80).aspx . Шифоз, вы можете восстановить некоторые очки, спросив что-нибудь о программистах, например: «Какой у вас любимый цвет программирования в RGB?»
public void func() < < ArrayList l = new ArrayList(); >System.out.println("Hello"); >
Это дает вам ограниченную область применения предложения using, но нет интерфейса IDisposable для вызова кода завершения. Вы можете использовать try <> catch () <> Наконец <>, но в нем нет сахара в использовании. Между прочим, использование финализаторов в Java — вообще плохая идея.
Я думаю, вы можете добиться чего-то похожего на блок «using», реализуя анонимный внутренний класс. Как Spring делает с «шаблонами Дао».
Самое близкое, что вы можете найти в 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) <> > >
C# vs Java: Using
Отталкнемся от директивы/оператора using в C# и посмотрим что там есть в Java.
Директива / Оператор using
Импорт типов
using позволяет использовать типы описанные в других пространствах имен без указания fully-qualified-name
using MyApplication.MyPackage; // . var myClass = new MyClass();
тут мы можем использовать myClass не указывая молный путь к классу MyApplication.MyPackage.MyClass
Псевдонимы
Псевдонимы можно создавать для пространства имен или конкретных типов как показанно ниже
using MyPackageAlias = MyApplication.MyPackage; // or for type alias using ClassToUse = MyApplication.MyPackage.MyClass;
С помощью using можно сделать псевдоним на параметризированный generic:
using IntListAlias = Listint>; //. var list = new IntListAlias(); list.Add(42);
Глобальный импорт через using
- Действие using распространяется на текущий файл.
- using может быть объявлен в начале файла или в начале пространства имен.
С помощью global , сделав только одно объявление, можно импортировать содержимое пространства имен во всех файлах проекта.
global using MyApplication.MyPackage;
Содержимое покате MyPackage будет импортировано во все файлы проекта.
Глобальный импорт через файл проекта
Другой способ глобально подключить пространство имен — это файл проекта.
. Include="MyApplication.MyPackage" /> .
Импорт статических членов классов
В случае когда наш тип MyClass содержит статические члены или вложенные типы — мы можем импортировать только их и использовать их без указания типа MyClass .
// for class namespace MyApplication.MyPackage class MyClass static int Add(int a, int b) return a + b; > > > // we can use it as using static MyApplication.MyPackage.MyClass; // . var sum = Add(1, 2);
Аналогично для вложенных типов.
Еще пример из документации:
using static System.Console; using static System.Math; class Program static void Main() WriteLine(Sqrt(3*3 + 4*4)); > >
Wildcard Imports
Если мы пишем using MyApplication.MyPackage; — это значит что мы делаем доступными все типы из пространства имен MyApplication.MyPackage . Такое поведение вполне точно описывает что мы подразумеваем под wildcard imports когда в Java пишем import MyApplication.MyPackage.*; . Получается, что wildcard imports для using в C# — это поведение по умолчанию.
Важно отметить что в C# мы не можем импортировать конкретный тип c using name
using MyApplication.MyPackage.MyClass; // incorrect
такое возможно только с использованием алиаса
using MyClassAlias = MyApplication.MyPackage.MyClass; // correct // or with same name using MyClass = MyApplication.MyPackage.MyClass; // correct
но такой подход уже выглядит как будто мы делаем что-то не правильно.
Инструкция using и IDisposable
Как это работает?
using в C# может использоваться как оператор для автоматического закрытия объектов имплементирующих IDisposable.
string txt = String.Empty; using (StreamReader sr = new StreamReader(filename)) txt = sr.ReadToEnd(); >
В этом примере при входе в блок using будет создан поток StreamReader , а при выходе этот поток будет закрыт посредствам вызова метода Dispose() у StreamReader .
- using похож на try-with-resources в Java.
- await using используется для IAsyncDisposable
- в using можно передать объект сласса имплементирующего IDisposable
var reader = new StringReader(manyLines); using (reader) . >
using (StringReader left = new StringReader(numbers), right = new StringReader(letters)) . >
IDisposable Interface
Интерфейс для реализации освобождения неуправляемых ресурсов.
Стоит быть аккуратных, возможны проблемы если метод Dispose не будет вызван и ресурсы не будут освобождены. Как решение этой проблемы документация предлагает следующее:
Because the IDisposable.Dispose implementation is called by the consumer of a type when the resources owned by an instance are no longer needed, you should either wrap the managed object in a SafeHandle (the recommended alternative), or you should override Object.Finalize to free unmanaged resources in the event that the consumer forgets to call Dispose.
IAsyncDisposable Interface
Интерфейс для реализации асинхронного освобождения неуправляемых ресурсов.
А что там в Java?
Все немного похоже и немного другое чем в C#. Аналог для using директивы — это import. А для using оператора — это try-with-resources.
Рассмотрим далее подробнее.
import как аналог using
Импортировать тип из другого пакета можно так
import MyApplication.MyPackage.MyClass; // . var x = new MyClass();
тут стоит заметить что мы импортируем не все содержимое пакета, а конкретный тип.
Импорт статических членов классов
В Java мы можем импортировать статический член используя import static
import static MyApplication.MyPackage.MyClass.staticMethid;
это даст нам возможность использовать функцию staticMethid в коде текущего файла без указания имен пакета и класса.
import static java.lang.Math.cos; import static java.lang.Math.PI; double r = cos(PI * theta);
Глобальный импорт как c global using
Wildcard Imports
Такой подход в Java будем считать не самым лучшим выбором при написании кода, так как используя это:
import MyApplication.MyPackage.*;
мы можем неявно принести в нашу реализацию класс который мы бы не хотели импортировать.
Поэтому, в Java подход по умолчанию — это импорт только нужного типа вот так:
import MyApplication.MyPackage.MyClass;
try-with-resources
Как это работает?
В Java try (если он with-resources) умеет «закрывать» объекты. Совсем как using в C#.
Мы можем использовать объект, реализующий интерфейс AutoCloseable , как приведено ниже. try в этом случае, помимо своей обычной работы по контролю за исключениями, вызовет метод close() для освобождения ресурсов в конце работы своего блока.
try (PrintWriter writer = new PrintWriter(new File("test.txt"))) writer.println("Hello World"); >
AutoCloseable Interface
Все как в C# для IDisposable только в Java и для AutoCloseable и название метода другое.
An object that may hold resources (such as file or socket handles) until it is closed. The close() method of an AutoCloseable object is called automatically when exiting a try-with-resources block for which the object has been declared in the resource specification header.
Conclusion
Мне показалось что в C# с using больше способов выстрелить себе в ногу. Возможно это из-за: