Есть ли что-то как Python с менеджером по контексту в Java?
Например, скажите, что я хочу сделать что-то как следующее:
getItem(itemID){
Connection c = C.getConnection();
c.open();
try{
Item i = c.query(itemID);
}catch(ALLBunchOfErrors){
c.close();
}
c.close();
return c;
}
где в Python я просто имею:
with( C.getConnection().open() as c):
Item i = c.query(itemID);
return i;
На данный момент нет; Java до сих пор не добавила синтаксического сахара для этого шаблона. Тем не менее, он не будет таким чистым, как с
(Python) или с использованием
(C #), но вы можете хотя бы немного очистить это, просто вызвав c.close ()
внутри блока finally
, а не дважды, как вы это делали:
try {
// use c
} finally {
c.close()
}
Это также приводит его в соответствие с тем, как с
и Фактически реализованы с использованием
, которые представляют собой блок try..finally
(а не try..catch
).
Как сказал цаман, секрет наконец используется; в общем:
Resource r = allocateResource();
try {
// use resource
}
finally {
r.dispose();
}
Здесь следует отметить:
Если у вас есть несколько ресурсов для распределения, общий шаблон применяется чисто, но это часто не очевидно для новичков:
Resource1 r1 = allocateResource1();
try {
// code using r1, but which does not need r2
Resource r2 = allocateResource2();
try {
// code using r1 and r2
}
finally {
r2.dispose();
}
}
finally {
r1.dispose();
}
и так далее, и так далее, если у вас есть больше ресурсов для распределения. Если у вас есть несколько из них, вы наверняка захотите попытаться избежать глубокого вложения операторов try ... finally. Не надо. Вы можете получить правильное освобождение ресурсов и обработку исключений, не вкладывая так много операторов try ... finally, но получить все правильно без вложенности try ... finally даже уродливее, чем глубокое вложение.
Если вам часто нужно использовать набор ресурсов, вы можете реализовать метод на основе функторов, чтобы избежать повторения, например:
interface WithResources {
public void doStuff(Resource1 r1, Resource2 r2);
}
public static void doWithResources(WithResources withResources) {
Resource r1 = allocateResource1();
try {
Resource r2 = allocateResource2();
try {
withResources.doStuff(r1, r2);
}
finally {
r2.dispose();
}
}
finally {
r1.dispose();
}
}
Что затем вы можете использовать следующим образом:
doWithResources(new WithResources() {
public void doStuff(Resource1 r1, Resource2 r2) {
// code goes here
}
});
doWithResources будет автоматически обрабатывать выделение и правильное освобождение, и ваш код будет иметь меньше повторений (что хорошо). Однако:
, два момента, которые, я надеюсь, будут решены в Java 7.
Вы можете найти такой код в Spring, например:
Есть альтернатива, использующая универсальную оболочку вроде этой:
final _<Item> item = new _<Item>();
final _<Connection> c = new _<Connection>();
with( factory, c, new Runnable() {
public void run(){
item._ = c._.query( itemId );
}
});
return item._;
ПРИМЕЧАНИЕ. Способ Java - это тот, который вы только что описали. Другой - просто для "развлечения" и экспериментов:
_
- это общая оболочка, а with
функция - это служебный класс, определенный где-то еще как:
class WithUtil {
public static void with( ConnectionFactory factory,
_<Connection> c, Runnable block ) {
try {
c._ = factory.getConnection();
c._.open();
block.run();
} catch( Exception ioe ){
}finally{
if( c._ != null ) try {
c._.close();
} catch( IOException ioe ){}
}
}
}
In строгой теории, вы можете повторно использовать ее для выполнения других задач, например, для удаления элемента:
public void deleteItem( final int itemId ) {
final _<Connection> c = new _<Connection>();
with( factory, c, new Runnable() {
public void run(){
Item item = c._.query( itemId );
if( ! item.hasChildren() ) {
c._.delete( item );
}
}
});
}
или обновления его
public void update( final int itemId, String newName ) {
final _<Connection> c = new _<Connection>();
with( factory, c, new Runnable() {
public void run(){
Item item = c._.query( itemId );
item.setName( newName );
c._.update( item );
}
});
}
без необходимости повторной интеграции try / catch.
Вот полная рабочая демонстрация , которая подтверждает концепцию (и больше ничего не делает)