Resource Management

The previous section on memory management explains the differences between Java and Rust when it comes to GC, ownership and finalizers. It is highly recommended that you read it.

This section is limited to providing an example of a fictional database connection involving a SQL connection to be properly closed/disposed/dropped.

Here's the Java version:

import java.sql.Connection;

public class DatabaseConnection implements AutoCloseable {

    final String connectionString;
    Connection connection; // the Connection type implements AutoCloseable

    public DatabaseConnection(String connectionString) {
        this.connectionString = connectionString;
    }

    @Override
    public void close() throws Exception {
        // making sure to close the Connection
        this.connection.close();
        System.out.println("Closing connection: " + this.connectionString);
    }
}

// try-with-resources statement
try (
        var db1 = new DatabaseConnection("server=A; database=db1");
        var db2 = new DatabaseConnection("server=A; database=db2")
        ) {
    // ...code using "db1" and "db2"...
} // "close()" of "db1" and "db2" called here; when their scope ends

And here's the Rust equivalent:

struct DatabaseConnection(&'static str);

impl DatabaseConnection {
    // ...functions for using the database connection...
}

impl Drop for DatabaseConnection {
    fn drop(&mut self) {
        // ...closing connection...
        self.close_connection();
        // ...printing a message...
        println!("Closing connection: {}", self.0)
    }
}

fn main() {
    let _db1 = DatabaseConnection("Server=A;Database=DB1");
    let _db2 = DatabaseConnection("Server=A;Database=DB2");
    // ...code for making use of the database connection...
} // "Dispose" of "db1" and "db2" called here; when their scope ends