2010-11-14 14 views
5

Nhìn vào phương pháp của tôi, tôi không chắc tôi phải sử dụng ba khối try/catch riêng biệt. Tôi có nên sử dụng duy nhất cho toàn bộ phương pháp? Thực hành tốt là gì?Nên nhiều khối try/catch trong một phương pháp được kết hợp

public void save(Object object, File file) {  

     BufferedWriter writter = null; 

     try { 
      writter = new BufferedWriter(new FileWriter(file)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     Dictionary dictionary = (Dictionary)object; 
     ArrayList<Card> cardList = dictionary.getCardList(); 
     for (Card card: cardList) { 
      String line = card.getForeignWord() + "/" + card.getNativeWord(); 
      try { 
       writter.write(line); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     try { 
      writter.flush(); 
      writter.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

Trả lời

11

Bạn chắc chắn không muốn có ba khối riêng biệt với mã như vậy. Trong khối đầu tiên, bạn đang gặp phải lỗi thiết lập writer, nhưng sau đó trong các khối tiếp theo, bạn đang sử dụngwriter, điều này không có ý nghĩa nếu khối đầu tiên không thành công. Bạn sẽ kết thúc việc ném NullPointerException khi xảy ra lỗi I/O   — không lý tưởng. :-)

Có rất nhiều chỗ cho phong cách trong công cụ này, nhưng đây là một sự diễn giải lại khá chuẩn của chức năng của bạn. Nó chỉ sử dụng hai khối (mặc dù bạn có thể chọn để thêm lại một phần ba, xem các chú thích trong code):

public void save(Object object, File file) {  

    BufferedWriter writter = null; 

    try { 
     writter = new BufferedWriter(new FileWriter(file)); 

     Dictionary dictionary = (Dictionary)object; 
     ArrayList<Card> cardList = dictionary.getCardList(); 
     for (Card card: cardList) { 
      String line = card.getForeignWord() + "/" + card.getNativeWord(); 
      writter.write(line); // <== I removed the block around this, on 
           // the assumption that if writing one card fails, 
           // you want the whole operation to fail. If you 
           // just want to ignore it, you would put back 
           // the block. 
     } 

     writter.flush(); // <== This is unnecessary, `close` will flush 
     writter.close(); 
     writter = null; // <== null `writter` when done with it, as a flag 
    } catch (IOException e) { 
     e.printStackTrace(); // <== Usually want to do something more useful with this 
    } finally { 
     // Handle the case where something failed that you *didn't* catch 
     if (writter != null) { 
      try { 
       writter.close(); 
       writter = null; 
      } catch (Exception e2) { 
      } 
     } 
    } 
} 

Lưu ý về khối finally: Ở đây, bạn có thể xử lý các trường hợp bình thường (trong trường hợp này writter sẽ là null) hoặc bạn có thể đang xử lý ngoại lệ mà bạn không nắm bắt (điều này không phải là bất thường, một trong những điểm ngoại lệ chính là xử lý những gì phù hợp ở cấp này và chuyển bất kỳ thứ gì khác cho người gọi) . Nếu writter!null, hãy đóng. Và khi bạn đóng cửa sổ, hãy ăn bất kỳ ngoại lệ nào xảy ra hoặc bạn sẽ làm mờ sự cố ban đầu. (Tôi có các chức năng tiện ích để đóng mọi thứ trong khi ăn một ngoại lệ, cho chính xác tình huống này. Đối với tôi, điều đó có thể là writter = Utils.silentClose(writter); [silentClose luôn trả về null]). Bây giờ, trong mã này bạn có thể không mong đợi các ngoại lệ khác, nhưng A) Bạn có thể thay đổi điều đó sau, và B) RuntimeException s có thể xảy ra tại bất kỳ thời điểm nào. Tốt nhất để quen với việc sử dụng mẫu.

+1

Cảm ơn bạn đã giải thích tốt như vậy. – Eugene

+0

@AndroidNoob: Đừng lo! Vui mừng đã giúp. –

+0

@ T.J. Crowder tại sao bạn đóng 'writer' bên trong' try' block? Không phải là nó thừa? –

1

Đó là vấn đề về hương vị - không có câu trả lời đúng.

Cá nhân, tôi thích một khối thử/nắm bắt. Nếu tôi thấy nhiều người trong số họ, tôi bắt đầu lo lắng rằng phương pháp của tôi đang làm quá nhiều và trở nên quá lớn. Đó là một dấu hiệu cho thấy đây có thể là lúc để phá vỡ nó thành những phương pháp nhỏ hơn.

Đây là cách tôi muốn viết phương pháp đó:

public void save(Object object, File file) throws IOException 
{ 

    BufferedWriter writer = null; 

    try { 
    writer = new BufferedWriter(new FileWriter(file)); 

    Dictionary dictionary = (Dictionary) object; 
    ArrayList<Card> cardList = dictionary.getCardList(); 
    for (Card card : cardList) 
    { 
     String line = card.getForeignWord() + "/" + card.getNativeWord(); 
     writer.write(line); 
    } 
    } 
    finally 
    { 
     IOUtils.close(writer); 
    }  
} 

Tôi muốn có một lớp IOUtils rằng sẽ đóng gói đóng cửa đúng đắn của con suối, độc giả, và nhà văn. Bạn sẽ viết mã đó một lần nữa và một lần nữa. Tôi muốn làm cho nó một lót như một phương pháp tĩnh trong một lớp học - hoặc sử dụng Apache Commons IO Utils JAR nếu tôi không nhớ một phụ thuộc.

+2

Có thực sự không có câu trả lời đúng, nhưng imho nó không chỉ về hương vị – Peter

+0

Đồng ý, Peter. Có vấn đề cố gắng/cuối cùng, vv – duffymo

1

Điều gì là tốt tùy thuộc vào mã của bạn nhằm làm gì. Ví dụ, try/catch thứ hai nằm bên trong một vòng lặp, có nghĩa là, nó sẽ xử lý tất cả card trong danh sách, ngay cả khi quá trình xử lý không thành công. Nếu bạn sử dụng một trong số try/catch cho toàn bộ phương pháp, hành vi này sẽ bị thay đổi. Sử dụng một try/catch nếu bản ngã của bạn cho phép.

0

Trong trường hợp cụ thể của I/OI khuyên bạn nên xem một số loại libar phổ biến có sẵn như Guava và Jakarta commons. Họ có một số kịch bản tốt đẹp để thực hiện đóng cửa im lặng.

Ví dụ: Commons IO IOUtils

Đây có thể dọn dẹp mã của bạn khá một chút

0

Tôi thích viết hai khối try, một cho cuối cùng và một cho việc nắm bắt. Bởi vì cách nó được viết, bạn không bao giờ thiết lập writter để null, cũng không làm bạn phải kiểm tra chống lại null khi đóng cửa. Vấn đề duy nhất là một ngoại lệ trong khi việc đóng sẽ ẩn một ngoại lệ trong khi xử lý, nhưng nó chỉ là vấn đề nếu bạn muốn xử lý hai ngoại lệ khác nhau.

public void save(Object object, File file) { 
    try { 
     BufferedWriter writter = new BufferedWriter(new FileWriter(file)); 
     try { 
      Dictionary dictionary = (Dictionary)object; 
      ArrayList<Card> cardList = dictionary.getCardList(); 
      for (Card card: cardList) { 
       String line = card.getForeignWord() + "/" + card.getNativeWord(); 
       writter.write(line); 
      } 
     } finally { 
      writter.flush(); 
      writter.close(); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); //Or something more useful 
    } 
} 
Các vấn đề liên quan