5

Vì vậy, tôi có một khối thử/cuối cùng. Tôi cần thực hiện một số phương thức trong khối cuối cùng. Tuy nhiên, mỗi một trong những phương pháp đó có thể ném một ngoại lệ. Có cách nào để đảm bảo rằng tất cả các phương pháp này được gọi là (hoặc cố gắng) mà không có lồng nhau cuối cùng khối?Trong java, có cách nào để đảm bảo rằng nhiều phương thức được gọi trong một khối cuối cùng?

Đây là những gì tôi làm ngay bây giờ, mà là khá xấu xí:

protected void verifyTable() throws IOException { 
    Configuration configuration = HBaseConfiguration.create(); 
    HTable hTable = null;            

    try { 
     hTable = new HTable(configuration, segmentMatchTableName);  

     //... 
     //various business logic here 
     //... 

    } finally {       
     try { 
      try { 
       if(hTable!=null) { 
        hTable.close(); //This can throw an IOException 
       }    
      } finally { 
       try { 
        generalTableHelper.deleteTable(configuration, segmentMatchTableName); //This can throw an IOException 
       } finally { 
        try { 
         generalTableHelper.deleteTable(configuration, wordMatchTableName); //This can throw an IOException 
        } finally { 
         generalTableHelper.deleteTable(configuration, haplotypeTableName); //This can throw an IOException  
        } 
       } 
      }        
     } finally { 
      HConnectionManager.deleteConnection(configuration, true); //This can throw an IOException 
     } 
    }    
} 

Có cách nào hơn-nhã để làm điều này?

+3

Bạn có thể trích xuất chúng ra thành một phương pháp dọn dẹp. – Reimeus

+0

'Có cách nào để đảm bảo rằng tất cả các phương thức này được gọi (hoặc cố gắng) ** mà không lồng nhau cuối cùng là khối **?' –

Trả lời

2

Tiêu chuẩn (làm việc) cách để quản lý tài nguyên ngay trong Java (nguyên tắc áp dụng cho các ngôn ngữ khác cũng) là:

Resource resource = acquire(resource); 
try { 
    use(resource); 
} finally { 
    resource.release(); 
} 

Hoặc sử dụng các phím tắt (với thêm một chút về sự thông minh) trong hiện tại phiên bản của Java SE:

try (Resource resource = acquire(resource)) { 
    use(resource); 
} 

(Như Joe K chỉ ra, bạn có thể cần phải quấn tài nguyên để làm cho nó xác nhận với giao diện cụ thể mà ngôn ngữ Java phụ thuộc.)

Hai nguồn lực, và bạn chỉ cần áp dụng các thành ngữ hai lần:

Resource resource = acquire(resource); 
try { 
    SubResource sub = resource.acquire(); 
    try { 
     use(sub); 
    } finally { 
     sub.release(); 
    } 
} finally { 
    resource.release(); 
} 

Và trong Java SE 7:

try (
    Resource resource = acquire(resource); 
    SubResource sub = resource.acquire() 
) { 
    use(resource, sub); 
} 

Ưu điểm thực sự tuyệt vời của tính năng ngôn ngữ mới là xử lý tài nguyên là thường xuyên hơn không bị hỏng khi viết ra.

Bạn có thể xử lý ngoại lệ phức tạp hơn. Ví dụ: bạn không muốn ném các ngoại lệ cấp thấp như IOException đến ứng dụng thích hợp - bạn có thể muốn bọc trong một số loại phụ của RuntimeException. Điều này có thể, với sự rõ ràng điển hình của Java, được thừa nhận bằng cách sử dụng thành ngữ Thực thi xung quanh (xem this excellent question). Từ Java SE 8, cũng sẽ có cú pháp ngắn hơn với ngữ nghĩa khác nhau ngẫu nhiên.

with(new ResourceSubAction() { public void use(Resource resource, SubResource sub) { 
    ... use resource, sub ... 
}}); 
0

Nói chung, không có cách nào thoát khỏi điều này. Bạn cần nhiều khối cuối cùng.

Tuy nhiên, tôi không muốn nhận xét về mã cụ thể của bạn, cho dù đó có phải là thiết kế phù hợp hay không. Nó chắc chắn trông khá kỳ quặc.

+0

Vâng, mã có ý nghĩa hơn nếu bạn có thể thấy logic nghiệp vụ. Tôi bỏ nó ra vì lợi ích ngắn gọn. – sangfroid

0

Không có cách nào tôi sợ. Có một mô hình tương tự khi đóng tài nguyên io. Ví dụ: bạn làm gì khi đóng một tệp phát ra một IOException? Thông thường bạn chỉ cần bỏ qua nó. Vì đây là một chút nếu một mô hình chống họ giới thiệu cú pháp thử trong Java 7. Ví dụ của bạn mặc dù tôi nghĩ rằng không có tùy chọn nào khác. Có lẽ đặt từng phương pháp cuối cùng vào phương pháp riêng của nó để làm cho nó rõ ràng hơn

0

Để gọi nhiều phương thức từ một khối cuối cùng, bạn phải đảm bảo rằng không có phương pháp nào được ném - đó là một ý tưởng hay. khối sẽ ghi đè lên ngoại lệ hoặc giá trị trả lại được ném từ try/catch.

Trường hợp sử dụng phổ biến nhất là kết nối tệp hoặc cơ sở dữ liệu, trong trường hợp bạn viết phương thức "đóng lặng lẽ" (hoặc sử dụng phương thức từ thư viện hiện có, chẳng hạn như Jakarta Commons IO). Nếu những thứ bạn cần làm sạch không cho phép bạn sử dụng một phương pháp đã tồn tại từ trước, bạn viết phương pháp của riêng mình (trong trường hợp của bạn là deleteTableQuietly()).

Nếu bạn đang sử dụng JDK-7, bạn cũng có thể sử dụng cấu trúc "try with resource".

2

Nếu đây là Java 7, bạn có thể xem xét sử dụng cấu trúc thử nghiệm với tài nguyên mới. Bạn có thể cần tạo một số trình bao bọc cơ bản AutoCloseable để xóa các bảng.

0

Bạn có thể tạo lớp trừu tượng Hành động với phương thức thực thi và lấy được từ lớp đó một lớp cho mỗi phương thức ném ngoại lệ mà bạn muốn gọi, gọi phương thức này từ phương thức thực thi. Sau đó, bạn có thể tạo một danh sách các hành động và lặp qua các phần tử của danh sách, gọi phương thức thực thi của chúng trong một khối thử cuối cùng, bỏ qua các ngoại lệ.

0
deleteTableSilently(table1);  
deleteTableSilently(table2);  
deleteTableSilently(table3); 


deleteTableSilently() 
    try 
     deleteTable() 
    catch whatever 
     log.error(); 
0

Xem xét sử dụng khuôn khổ java.util.concurrent - nếu bạn mã mỗi cuộc gọi như một Callable cá nhân (tên hoặc vô danh), bạn có thể sử dụng ExecutorService.invokeAll.

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