2010-05-31 35 views
6

Có điều gì đó giống như Python với trình quản lý ngữ cảnh trong Java không?Mô phỏng câu lệnh của python Với java

Ví dụ nói rằng tôi muốn làm một cái gì đó như sau:

getItem(itemID){ 
    Connection c = C.getConnection(); 
    c.open(); 
    try{ 
    Item i = c.query(itemID); 
    }catch(ALLBunchOfErrors){ 
     c.close(); 
    } 

    c.close(); 
    return c; 
} 

nơi trong python Tôi chỉ có:

with(C.getConnection().open() as c): 
    Item i = c.query(itemID); 
    return i; 
+2

Tôi không biết nhiều về 'with' hoặc Python cho vấn đề đó, nhưng nếu nó giống như C# 's' using', điều này đã được trả lời rất gần đây: http://stackoverflow.com/questions/ 2943542/using-keyword-in-java –

+0

+1 nhưng: '[const]' '[final]' cũng tồn tại, vì vậy '[with]' cũng nên có một thẻ. Tôi chưa thể tạo ra nó. – n611x007

Trả lời

5

Không vào lúc này; Java vẫn chưa thêm đường cú pháp cho mẫu này. Tuy nhiên, nó sẽ không được sạch sẽ như with (Python) hoặc using (C#), nhưng bạn có thể ít nhất làm sạch điều đó một chút bằng cách chỉ có một cuộc gọi đến c.close() bên trong một khối finally, thay vì hai lần như bạn đã thực hiện:

try { 
    // use c 
} finally { 
    c.close() 
} 

này cũng mang đến cho nó phù hợp với cách cả withusing đang thực sự thực hiện, đó là một khối try..finally (không phải là một try..catch).

+0

Cảm ơn ... Tôi khách tôi cũng có thể sử dụng mẫu phương thức mẫu, yêu cầu phân cấp lớp xấu xí. Chúc mừng. – drozzy

3

Như tzaman đã nói, bí mật đang sử dụng cuối cùng; nói chung:

Resource r = allocateResource(); 
try { 
    // use resource 
} 
finally { 
    r.dispose(); 
} 

Những điều cần lưu ý ở đây:

  • thử và cuối cùng mỗi tạo ra một phạm vi khác nhau. Vì vậy, phân bổ tài nguyên của bạn trong mệnh đề try sẽ không hoạt động, vì nó sẽ không được hiển thị trong mệnh đề cuối cùng - bạn phải khai báo biến của tài nguyên trước câu lệnh try.

Nếu bạn có nhiều nguồn lực để phân bổ, mô hình chung áp dụng sạch, nhưng điều này thường không phải là hiển nhiên đối với người mới bắt đầu:

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

, và vân vân và vân vân nếu bạn có nhiều nguồn lực để phân bổ . Nếu bạn có một vài người trong số họ, bạn chắc chắn sẽ bị cám dỗ để cố gắng và tránh làm tổ sâu của cố gắng ... cuối cùng tuyên bố. Đừng. Bạn có thể nhận được tài nguyên deallocation và xử lý ngoại lệ ngay mà không làm tổ rất nhiều cố gắng ... cuối cùng tuyên bố, nhưng nhận được nó ngay mà không làm tổ thử ... cuối cùng thậm chí còn xấu hơn sâu làm tổ.

Nếu bạn thường xuyên cần phải sử dụng một tập hợp các nguồn lực, bạn có thể thực hiện một phương pháp functor dựa trên để tránh sự lặp lại, một cái gì đó như:

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

nào thì bạn có thể sử dụng như thế này:

doWithResources(new WithResources() { 
    public void doStuff(Resource1 r1, Resource2 r2) { 
     // code goes here 
    } 
}); 

doWithResources sẽ tự động xử lý phân bổ và deallocation chính xác, và mã của bạn sẽ có ít sự lặp lại (đó là một điều tốt). Tuy nhiên:

  • cú pháp của Java cho các lớp học vô danh là quá dài dòng
  • ngoại lệ Kiểm tra trong vòng doStuff những điều phức tạp quá nhiều

, hai điểm mà tôi hy vọng sẽ được giải quyết trong Java 7.

Bạn có thể tìm thấy loại mã này trong suốt mùa xuân, ví dụ:

+0

Cảm ơn, điều functor trông thú vị. Để xấu không có đường để đơn giản hóa nó. – drozzy

+0

Ngoài ra - bạn không có nghĩa là close() thay vì vứt bỏ()? Java có một giao diện Closeable. – drozzy

+0

"vứt bỏ" chỉ nghe có vẻ chung chung hơn :-p. Nó chỉ là mã giả :-p – alex

1

Có một sự thay thế sử dụng một wrapper chung như thế này:

final _<Item> item = new _<Item>(); 
final _<Connection> c = new _<Connection>(); 
with(factory, c, new Runnable() { 
    public void run(){ 
     item._ = c._.query(itemId); 
    } 
}); 
return item._; 

Chú ý: Cách Java là một trong những bạn vừa mô tả. khác này chỉ dành cho "vui vẻ" và thử nghiệm:

Các _ là một wrapper chung và with chức năng là một lớp tiện ích được xác định ở một nơi khác như:

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

Trong nghiêm ngặt lý thuyết, bạn có thể tái -Sử dụng nó để thực hiện những thứ khác, như xóa một mục:

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

hoặc cập nhật nó

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

Không cần phải tích hợp try/catch một lần nữa.

Dưới đây là một full working demo đó chứng minh khái niệm (và không làm bất cứ điều gì khác)

+0

Dấu gạch dưới ở mọi nơi có ý nghĩa gì? Tên biến tạm thời? – drozzy

+0

Đó không phải là Java (ngôn ngữ) mà là trình bao bọc lớp chung chung tôi đã tạo. Bạn có thể nghĩ rằng nó là một người nghèo vượt qua * tham chiếu * thay thế. Nó được định nghĩa là: 'class _ {public E _; } ': P – OscarRyz

+0

Xin lỗi, tôi vẫn không chắc chắn dấu gạch dưới là gì. Bạn đang nói rằng họ không phải là một phần của ngôn ngữ java ??? – drozzy

Các vấn đề liên quan