Hacker News new | ask | show | jobs
by FurrBall 4652 days ago
I look at Java code and it horrifies me. Java is great if your resource is memory. It turns into a horrible unsafe mess the moment your resources are not memory.

  //C++ RAII goodness.
  void foo()
  {
  	conn.open();
  	file.open();
  	printer.activate();
  	//do stuff
  }
  
  //Java's lack of RAII is disturbing
  void foo()
  {
  	try{
  		conn.open();
  		file.open();
  		printer.activate();
  		//do stuff
  	}
  	catch(Exception e) { }
  	finally{
  		try {
  			conn.close();
  		}
  		catch(Exception ee) {}
  		finally{
  			try {
  				file.close();
  			}
  			catch(Exception eee) {}
  			finally {
  				try{
  					printer.close();
  				}
  				catch(Exceptoin eeee) {}
  			}
  		}
  	}
  }
2 comments

You can write bad code in any language. No experienced Java coder would write a code like this. Java has ARM blocks for dealing with deterministic resource cleanup.
Reality is there are many Java code bases which handle resources like this. For java 6 and below this not bad code; it is how you are forced to deal with resources.

Even with the new block syntax, you have painful nesting if the operation requires several disparate resources.

Blocks are an improvement, but not the same as RAII. A block is literally converted to a try-finally by the compiler. It is the same thing with a cleaner syntax. There is no safety added to the old Java way. A programmer can forget to put his stuff in a block and leak the resource the same as he forgets to use a try-finally. The onus is on the consumer, not the library writer.

With RAII the onus is removed from the consumer. The consumer writes safe code automatically, no onus to remember any special clean up idioms.

using/ARM/etc. make classes which own non-memory resources a lot less awkward to deal with, but one of the big wins of RAII is that the caller doesn't have to know or care that you have things which require special cleanup.
Agreed, however it is very easy to catch a forgotten close() automatically (IDEs do that), and, at least in my experience, most non-memory resources are used locally and not shared, so they are pretty easy.

On the other side, some programming techniques are hard or downright impossible without GC - e.g. heavy functional programming with immutable persistent structures.

Java 7 introduced a new language construct, called the try-with-resources statement, for automatic resource management:

    void foo() {
        try (open file or resource here) {
            // do stuff
        }
        // after try block, resource will close automatically
    }
This works with non-memory resources such as files, streams, sockets, and database connections.
Pasting a response:

Blocks are an improvement, but not the same as RAII. A block is literally converted to a try-finally by the compiler. It is the same thing with a cleaner syntax. There is no safety added to the old Java way. A programmer can forget to put his stuff in a block and leak the resource the same as he forgets to use a try-finally. The onus is on the consumer, not the library writer.

With C++ RAII the onus is removed from the consumer. The consumer writes safe code automatically, no onus to remember any special clean up idioms.

As long as the object is stack allocated or a member variable.
Well you do have to ban raw pointers. Heap allocation is safe with smart pointers.