How to define the anonymous inner class separately from the constructor block?
For example in my codes I want method2 do the same thing as method1 The only difference is method2 uses the Factory class to create the ClosableResultSet.
import java.sql.*;
public class Demo {
public static void main(String[] args) {
method1();
method2();
}
static void method1() {
Connection conn;
try {
conn = DriverManager.getConnection("jdbc:h2:C:/myDB", "sa", "sa");
String sql = "select * from Customers";
try (ClosableResultSet rs = new ClosableResultSet(conn, sql) {
@Override
public void handleError(SQLException e, String action) {
System.out.print(action + ": " + e.getMessage());
}
}) {
while (rs.next()) {
System.out.print("Name: " + rs.getString("name") + "\n");
}
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static void method2() {
String sql = "select * from Customers";
//here has the syntax errors
try (ClosableResultSet rs = Factory.createResultSet(sql) {
@Override
public void handleError(SQLException e, String action) {
System.out.print(action + ": " + e.getMessage());
}
}) {
while (rs.next()) {
System.out.print("Name: " + rs.getString("name") + "\n");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
import java.sql.*;
public class Factory {
public static ClosableResultSet createResultSet(String sql) throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:h2:C:/myDB", "sa", "sa");
return new ClosableResultSet(conn, sql);
}
}
import java.sql.*;
public class ClosableResultSet implements java.io.Closeable {
private ResultSet rs;
public ClosableResultSet(Connection conn, String sql) throws SQLException {
Statement stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
}
public Boolean next() {
try {
return rs.next();
} catch (SQLException e) {
handleError(e, "next");
return false;
}
}
public String getString(String columnLabel) {
try {
return rs.getString(columnLabel);
} catch (SQLException e) {
handleError(e, "get " + columnLabel);
return "";
}
}
@Override
public void close() {
try {
rs.close();
} catch (SQLException e) {
handleError(e, "close");
}
}
public void handleError(SQLException e, String action) {
// to be override
}
}
I don't want to declare the anonymous inner class in the Factory class, is there any lambda expression allow me to put it in method2?
You can create another Factory
method that takes a BiConsumer
in addition to the String sql
. Something like this:
import java.sql.*;
import java.util.function.BiConsumer;
public class Factory {
public static ClosableResultSet createResultSet(String sql) throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:h2:C:/myDB", "sa", "sa");
return new ClosableResultSet(conn, sql);
}
public static ClosableResultSet createResultSet(String sql, BiConsumer<SQLException, String> handler) throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:h2:C:/myDB", "sa", "sa");
return new ClosableResultSet(conn, sql) {
@Override
public void handleError(SQLException e, String action) {
handler.accept(e, action);
}
};
}
}
And then your method2
should be:
static void method2() {
String sql = "select * from Customers";
try (ClosableResultSet rs = Factory.createResultSet(
sql,
(e, action) -> System.out.print(action + ": " + e.getMessage())
)) {
while (rs.next()) {
System.out.print("Name: " + rs.getString("name") + "\n");
}
} catch (SQLException e) {
e.printStackTrace();
}
}