Closeable objects and using clauses

Closeable objects include objects such as data streams, reader or writer objects, and data channels. Many of the classes in the java.io package are closeable. For Gosu to recognize a valid closeable object, the object must have one of the following attributes:

  • Implements the java.io.Closeable interface, which contains only a single method called close with no arguments. Use a type that implements Closeable if possible for faster runtime performance.
  • Has a close method with no arguments, even if it does not implement the java.io.Closeable interface. This approach is slower at run time, because Gosu must use reflection (examining the type at run time) to find the method.

A type’s close method must release all resources owned by its base types by calling its parent type’s close method.

To ensure that resources clean up appropriately even under error conditions, you must design your close method so Gosu can call it multiple times without throwing an exception, even if the object is already closed.

The following example creates a new Java file writer instance (java.io.FileWriter) and uses the more verbose try and finally clauses:

var writer = new FileWriter("c:\\temp\\test1.txt")
try {
  writer.write( "I am text within a file." )
}
finally {
  if ( writer != null ) {
    writer.close()
  }
}

You can write more readable Gosu code with the using keyword:

using (var writer = new FileWriter("c:\\temp\\test1.txt")) {
  writer.write("I am text within a file.")
}

You can list multiple variables in the using clause:

uses java.io.FileReader
uses java.io.FileWriter
uses gw.util.StreamUtil

using (var reader = new FileReader("c:\\temp\\test1.txt"),
       var writer = new FileWriter("c:\\temp\\test2.txt")) {
  writer.write( StreamUtil.getContent( reader ) )
}

You can pass multiple objects to a using clause. In such cases, exit actions (closing, disposing, and unlocking) are executed in reverse order of the object declarations.

JDBC resources and using clauses

The following example demonstrates how to use a using clause with a JDBC (Java Database Connection) object.

uses java.sql.*

...

function sampleJdbc( con : Connection ) {
  using (var stmt = con.createStatement(),
         var rs = stmt.executeQuery("SELECT a, b FROM TABLE2")) {
    rs.moveToInsertRow()
    rs.updateString(1, "AINSWORTH")
    rs.insertRow()
  }
}