2010-07-22 23 views
18

Thông thường, khi giao dịch với mã Java IO, đây là những gì tôi đã viếtTôi có thể tránh như vậy cồng kềnh try ... catch block

FileOutputStream out = null; 
    try 
    { 
     out = new FileOutputStream("myfile.txt"); 
     // More and more code goes here... 
    } 
    catch (Exception e) 
    { 
    } 
    finally 
    { 
     // I put the close code in finally block, to enture the opened 
     // file stream is always closed even there is exception happened. 
     if (out != null) { 
      // Another try catch block, troublesome. 
      try { 
       out.close(); 
      } catch (IOException ex) { 
      } 
     } 
    } 

Như bạn có thể thấy, trong khi tôi cố gắng để đóng dòng tập tin, tôi cần phải đối phó với một thử khác ... bắt khối.

Nhìn phiền :(

Có cách nào tôi có thể tránh? Tôi không cảm thấy thoải mái trong việc đưa mã gần trong phi khối finally, như ngoại lệ do mã khác sẽ làm cho không có cơ hội cho "gần "được gọi.

+1

Ai đó ở đâu đó đồng ý với bạn: http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000011.html - Khối ARM trong JDK7. --JA – andersoj

+0

Ồ. Là Joshua Bloch :) –

Trả lời

13

Điều quan trọng là bạn đóng luồng cuối cùng. Bạn có thể đơn giản hóa quy trình này bằng phương pháp tiện ích như:

public static void closeStream(Closeable closeable) { 
    if(null != closeable) { 
     try { 
     closeable.close(); 
     } catch(IOException ex) { 
     LOG.warning("Failed to properly close closeable.", ex); 
     } 
    } 
    } 

Tôi làm cho nó ít nhất là ghi nhật ký lỗi gần dòng. Cách sử dụng sau đó sẽ trở thành:

FileOutputStream out = null; 
try 
{ 
    out = new FileOutputStream("myfile.txt"); 
    // More and more code goes here... 
} 
catch (Exception e) 
{ 
} 
finally 
{ 
    closeStream(out); 
} 

Trong Java 7 Tôi tin rằng các luồng sẽ tự động bị đóng và cần phần lớn là dư thừa.

+0

Từ những gì tôi nghe trên SO, Java 7 cũng sẽ ngủ trong bản vá ướt. – kibibu

+0

Ý của bạn là "catch (IOException e)" thay vì "catch (Exception e)"? – janm

+0

Đó là một đoạn mã được dán của mã ví dụ gốc từ người dùng đặt câu hỏi. Nhưng có nó phải là IOException. – S73417H

1

tôi có xu hướng sử dụng các chức năng tiện ích cho việc này:

public static void safeClose(OutputStream out) { 
    try { 
    out.close(); 
    } catch (Exception e) { 
    // do nothing 
    } 
} 

làm thay đổi mã để hơi ngon miệng hơn:

FileOutputStream out = null; 
try { 
    out = new FileOutputStream("myfile.txt"); 
    // do stuff 
} catch (Exception e) { 
    // do something 
} finally { 
    safeClose(out); 
} 

Bạn có thể không thực sự làm tốt hơn nhiều trong Java ít nhất cho đến khi Java 7 khi (hy vọng) ARM ("Automatic Resource Management") blocks sẽ giúp phần nào.

+0

Khối ARM? Tôi có thể biết đó là gì không? –

+0

Một số điểm cho safeClose. Bạn cũng nên kiểm tra con trỏ null, đúng không? –

+0

@Yah đã thêm một liên kết về các khối ARM vào bài đăng. Đối với kiểm tra cho 'null', bạn có thể nhưng nó phần lớn là thừa. Nếu bạn ném một 'NullPointerException', nó sẽ bị bắt trong mệnh đề' catch'. Nhưng tất nhiên bạn có thể thêm kiểm tra đó nếu bạn muốn. – cletus

6

Automatic Resource Management sắp có trong Java 7 sẽ tự động cung cấp xử lý việc này. Cho đến lúc đó, các đối tượng như OutputStream, InputStream và các đối tượng khác triển khai giao diện Closeable từ Java 5. Tôi khuyên bạn nên cung cấp phương thức tiện ích để đóng an toàn các đối tượng này. Những phương pháp này thường ăn ngoại lệ, vì vậy hãy đảm bảo rằng bạn chỉ sử dụng chúng khi bạn muốn bỏ qua ngoại lệ (ví dụ: trong phương pháp cuối cùng). Ví dụ:

public class IOUtils { 
    public static void safeClose(Closeable c) { 
     try { 
      if (c != null) 
       c.close(); 
     } catch (IOException e) { 
     } 
    } 
} 

Lưu ý rằng phương pháp close() có thể được gọi nhiều lần, nếu nó đã được đóng lại cuộc gọi tiếp theo sẽ không có hiệu lực, vì vậy cũng cung cấp một lời kêu gọi đóng cửa trong thời gian hoạt động bình thường của khối try hợp ngoại lệ sẽ không bị bỏ qua.From the Closeable.close documentation:

Nếu dòng đã được đóng sau đó gọi phương pháp này không có tác dụng

Vì vậy, đóng dòng đầu ra trong dòng chảy thường xuyên của các mã và phương pháp safeClose sẽ chỉ thực hiện chặt chẽ nếu có điều gì thất bại trong khối thử:

FileOutputStream out = null; 
try { 
    out = new FileOutputStream("myfile.txt"); 
    //... 
    out.close(); 
    out = null; 
} finally { 
    IOUtils.safeClose(out); 
} 
1

Viết phương thức trông giống như dưới đây; gọi từ khối cuối cùng của bạn ...

static void wrappedClose(OutputStream os) { 
    if (os != null) { 
    try { 
     os.close(); 
    } 
    catch (IOException ex) { 
     // perhaps log something here? 
    } 
    } 
0

Tách riêng thử/nắm bắt và thử/cuối cùng là chặn.

try 
{ 
    FileOutputStream out = new FileOutputStream("myfile.txt"); 
    try 
    { 
     // More and more code goes here... 
    } 
    finally 
    { 
     out.close(); 
    } 
} 
catch (Exception e) 
{ 
    //handle all exceptions 
} 

Việc nắm bắt bên ngoài cũng sẽ bắt bất kỳ thứ gì được ném gần.

+0

Bạn càng đưa thêm mã vào khối thử, thì càng khó xử lý các ngoại lệ theo đúng cách. – Darron

+0

Mã duy nhất được thêm vào khối thử là out.close(). Tôi cho rằng một lỗi được ném bởi điều đó có thể cần phải được xử lý giống như bất kỳ lỗi nào do việc tạo hoặc sử dụng. – ILMTitan

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