Java Programming Worst Practices (v)

Source: Internet
Author: User
Tags finally block


Freeing resources without a finally block

The wrong wording:

public void save (File f)  throws  IOException {    OutputStream out = new  Bufferedoutputstream (New fileoutputstream (f));     out.write (...);     out.close ();   }  public void load (File f)   throws ioexception {    inputstream in = new  Bufferedinputstream (New fileinputstream (f));     in.read (...);     in.close ();   } 

The above code opens a file output stream, which is assigned a file handle by the operating system, but the file handle is a very scarce resource and must be reclaimed correctly by calling the appropriate Close method. In order to ensure that resources can still be recovered correctly under exceptional circumstances, they must be placed in the finally block. The above code uses Bufferedinputstream to wrap the file stream into a buffer stream, which causes the buffer stream to be written to disk when the Close method is called.  Failure to close will result in incomplete write data. For FileInputStream, the close operation in the finally block is ignored here directly.
If the Bufferedoutputstream.close () method performs well, there is a potential bug (http://bugs.sun.com/view_bug.do?bug_id=6335274) if it fails: When the flush operation is called inside the Close method, it is ignored if an exception occurs. Therefore, to minimize data loss, explicitly call the flush operation before you perform close.
The following code has a small flaw: if assigning a file stream succeeds, but allocating buffer stream failure (Oom this scenario) will cause the file handle to not be released correctly. This is generally not a concern, however, because the JVM's GC will help us clean it up.

The correct wording:

 code for your cookbook  public void save ()  throws  Ioexception {    file f = ...    outputstream  out = new bufferedoutputstream (New fileoutputstream (f));     try  {      out.write (...);       out.flush ();  // don ' t lose exception by  implicit flush on close    } finally {       out.close ();     }  }  public void load (File  F)  throws IOException {    InputStream in = new  Bufferedinputstream (New fileinputstream (f));    try {       in.read (...);     } finally {   &nbSp;  try { in.close (); } catch  (ioexception e)  { }     }  }

    database access also involves a similar scenario:

Car getcar (datasource ds, string plate)  throws SQLException {     Car car = null;    Connection c = null;     preparedstatement s = null;    resultset rs =  null;    try {      c =  Ds.getconnection ();       s = c.preparestatement ("Select make,  color from cars where plate=? ");       s.setstring (1, plate);       rs =  s.executequery ();      if  (Rs.next ())  {          car = new car ();          car.make = rs.getstring (1);         &Nbsp;car.color = rs.getstring (2);       }    }  finally {      if  (rs != null)  try {  Rs.close (); } catch  (sqlexception e)  { }      if   (S != null)  try { s.close (); } catch  (sqlexception e)   { }      if  (C != null)  try { c.close ();  } catch  (sqlexception e)  { }    }     return car;  }


Finalize method Misuse

The wrong wording:

public class Filebackedcache {private File backingstore; ... protected void Finalize () throws IOException {if (Backingstore! = null) {Backingstore.close          ();        Backingstore = null; }     }  }

This question effective Java This book has a detailed description. The main is that the Finalize method relies on the GC's call, which may be called either immediately or after a few days, so it is unpredictable. This is misleading in the JDK's API documentation: it is recommended to release I/O resources in this method.
The correct approach is to define a close method, which is then called by the external container to release the resource.

The correct wording:

public class Filebackedcache {private File backingstore;          ... public void close () throws IOException {if (Backingstore! = null) {backingstore.close ();        Backingstore = null; }     }  }

A autoclosable interface has been introduced in JDK 1.7 (Java 7). The Close method is called automatically when the variable (not the object) is outside the Try-catch Resource usage range.

Try (Writer w = new FileWriter (f)) {//Implements closable W.write ("abc"); W goes out of scope here:w.close () are called automatically in any case} catch (IOException e) {throw new Runtime  Exception (E.getmessage (), E); }


Misuse of the Thread.interrupted method

The wrong wording:

try {thread.sleep (1000);  } catch (Interruptedexception e) {//OK} or while (true) {if (thread.interrupted ()) break; }

This is mostly the interrupted static method, in addition to returning the current thread's interrupt state, also resets the current thread state.

The correct wording:

try {thread.sleep (1000);  } catch (Interruptedexception e) {thread.currentthread (). interrupt ();  } or while (true) {if (Thread.CurrentThread (). isinterrupted ()) break; }


Creating a thread when static variables are initialized

The wrong wording:

Class Cache {private static final timer Evictor = new timer (); }

The timer constructor will have a new thread inside, and the thread will inherit various properties from its parent thread (that is, the current thread).  such as context ClassLoader, threadlocal, and other security attributes (access rights). The thread that loads the current class may be indeterminate, such as a random thread in a thread pool. If you need to control the properties of a thread, it is best to put its initialization in a static method, so that the initialization will be determined by its callers.

The correct wording:

Class Cache {private static Timer evictor;          public static Setupevictor () {evictor = new Timer (); }  }


Canceled timer task still holds status

The wrong wording:

Final MyClass callback = this;          TimerTask task = new TimerTask () {public void run () {callback.timeout ();  }  };  Timer.schedule (task, 300000L);  try {dosomething ();  } finally {Task.cancel (); }

The above task contains an application for an external class instance, which will cause the reference to not be reclaimed by the GC immediately. Because the timer will remain TimerTask is released after a specified time. Therefore, the external class instance corresponding to the task will be reclaimed after 5 minutes.

The correct wording:

Timertask task = new job (this);   timer.schedule (task, 300000l);   Try {          dosomething ();   } finally  {          task.cancel ();  }     static class Job extends TimerTask {           private MyClass callback;           public job (Myclass callback)  {                   this.callback = callback;           }           Public boolean cancel ()  {                   callback = null;                   return super.cancel ();           }          public void run ()  {                   if  (callback == null)  return;                   callback.timeout ();           }  }




Java Programming Worst Practices (v)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.