Results 1 to 3 of 3
  1. #1
    b9136057 is offline Member
    Join Date
    Jul 2010
    Posts
    6
    Rep Power
    0

    Default try and resume next

    This is something about programming in Java, using try/catch mechanism. Generally, we use
    try/catch blocks in this form:

    Java Code:
    	try{
    		// statements that throws exception
    	}
    	catch(<SomeException> e){
    		// statements handle exception
    	}
    Here <SomeException> shown as templete can be replaced, such as IOException/Exception, etc..
    Let we see the following case in practice of above:

    Java Code:
    	FileOutputStream out;
    
    	try{
    		out=new FileOutputStream("123.txt");
    		out.write("abcdefgh".getBytes());
    		out.close();
    	}
    	catch(IOException ioe){
    		System.out.println("fail to write file");
    	}
    It is the reasonable code that we want to write "abcdefgh" to file "123.txt", and we often see
    some sample codes are in this form. But, do you really think so? In this case it write only 8 bytes
    to the file, yes, it's 'possibly' the right way. But, how about writing 1 GiB? Here is the code
    attempts to write 1 GiB as the same form:

    Java Code:
    	FileOutputStream out;
    	int i;
    
    	try{
    		out=new FileOutputStream("123.txt");
    
    		for(i=1<<27; i-->0; out.write("abcdefgh".getBytes()))
    			;
    
    		out.close();
    	}
    	catch(IOException ioe){
    		System.out.println("fail to write file");
    	}
    Imagine that after the stream was opened(say created) successfully and then encounters disk write
    error. You can simulate this by changing the path "123.txt" to a flash disk, and simply unplug it
    during the file is writing. So, where the exception will be thrown? Bingo! It's thrown by the write
    method.

    Now, the stream was opened and the program reaches the catch block. Who will take care of closing
    it? Are you waiting for the garbage collector? "Mom(Java's volatile mother, JVM) asks me to respect
    the belongings of others except what are garbage. ", says Java G. Collector. Yes, It is still a valid
    object until it lost the holder (let out=null) or the method returns, after the gc raises will close
    it implicitly and destroy this object. So, why do you place out.close() there? For only the normal
    cases? You don't need to do that if you agree the handling of abnormal situation.

    Assume that you have your own reason to close the stream explicitly (so do I). How we can do? Many
    programmers or even some IDE tools will suggest that to close the stream in the finally block. We
    might intuitively thought the code like this:

    Java Code:
    	FileOutputStream out;
    	int i;
    
    	try{
    		out=new FileOutputStream("123.txt");
    
    		for(i=1<<27; i-->0; out.write("abcdefgh".getBytes()))
    			;
    	}
    	catch(IOException ioe){
    		System.out.println("fail to write file");
    	}
    	finally{
    		out.close();
    	}
    Actually we can't just put a statement 'out.close();' in the finally block or the complier warns us
    'variable out might not have been initialized', because it was initialized in a try block. Moreover,
    the close method will throw an IOException - we need put another try/catch blocks in the finally block!
    Here's the correct version:

    Java Code:
    	FileOutputStream out=null;
    	int i;
    
    	try{
    		out=new FileOutputStream("123.txt");
    
    		for(i=1<<27; i-->0; out.write("abcdefgh".getBytes()))
    			;
    	}
    	catch(IOException ioe){
    		System.out.println("fail to write file");
    	}
    	finally{
    		try{
    			if(out!=null)
    				out.close();
    		}
    		catch(IOException ioe_){
    			System.out.println("fail to close file");
    		}
    	}
    "The finally block might provide us a better way for exception handling. "
    Do you really think so? Sorry, I DO NOT! That means we will make the nested try/catch blocks more nested
    if there are methods throw exception in each level of catch/finally blocks. Therefore, here I show the code
    to solve this in two styles.

    Style1:

    Java Code:
    	FileOutputStream out=null;
    	int i;
    
    	try{
    		out=new FileOutputStream("123.txt");
    
    		try{
    			for(i=1<<27; i-->0; out.write("abcdefgh".getBytes()))
    				;
    		}
    		catch(IOException ioe_){
    			System.out.println("fail to write file");
    		}
    
    		out.close();
    	}
    	catch(IOException ioe){
    		System.out.println("fail to open/close file");
    	}
    Style2:

    Java Code:
    	FileOutputStream out=null;
    	int i;
    
    	try{
    		out=new FileOutputStream("123.txt");
    	}
    	catch(IOException ioe){
    		System.out.println("fail to open/close file");
    	}
    
    	try{
    		if(out!=null)
    			for(i=1<<27; i-->0; out.write("abcdefgh".getBytes()))
    				;
    	}
    	catch(IOException ioe_){
    		System.out.println("fail to write file");
    	}
    
    	try{
    		if(out!=null)
    			out.close();
    	}
    	catch(IOException ioe){
    		System.out.println("fail to open/close file");
    	}
    Although Style1 made the code shorter, it made the nest deeper. If you are about to write a program
    that copies streams, you will found that you are even growing the nested blocks just a little better
    than using the finally block. In Style2, you need to do more check in the rear blocks; of course you
    can omit them all if you don't believe that catching exceptions will decrease in performance.

    Start from Java SE 1.5, we can get the line number of current statement or which cause exception via
    StackTraceElement. Once I think there might be a way to resume the execution of the try block through
    something relative to this object after exception caught up. But I just found nothing. Alternatively, I
    did some improve of using the try/catch blocks. Here's the code:

    Java Code:
    	FileOutputStream out=null;
    	int i, j;
    
    	for(i=0;; ++i)
    		try{
    			if(i<1){
    				out=new FileOutputStream("123.txt");
    
    				for(j=1<<27; j-->0;)
    					out.write("abcdefgh".getBytes());
    			}
    
    			if(i<2)
    				out.close();
    
    			System.out.println("all statements are tried");
    			break;
    		}
    		catch(Exception e){
    			System.out.println("any exception");
    		}
    
    	System.out.println("i="+i);
    The value of i let you know how many exceptions thrown, and you should be carefully designing the
    condition of each 'if' statement. In this case, I know the open/write/close may throws exception. If it
    failed on opening, will fail on closing either; the value of i will be 3 on exit. If the file opened successfully
    and failed on writing, the next loop will skip the block i<1; it closes the stream and exit with i=1.

    I share this idea because of I want to find a way to reduce the using of try/catch blocks, but did not
    found anything matching exactly what I want to. Hope it's useful for you, and maybe you can provide
    the best of implementation to this goal.
    Last edited by b9136057; 07-07-2010 at 12:00 PM.

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Moved to Java Blogs as the original post is not a New to Java question and in fact is not a question at all.

  3. #3
    b9136057 is offline Member
    Join Date
    Jul 2010
    Posts
    6
    Rep Power
    0

    Default

    Thank you, Fubarable.
    Now I know where I should put this kind of articles.
    Thanks again for removing the mispelling one.

Similar Threads

  1. Trying to get the resume verbage right...
    By Hagrid1960 in forum Jobs Discussion
    Replies: 0
    Last Post: 01-16-2009, 07:35 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •