Java 匿名内部 class 声明
Java anonymous inner class declaration
如何与构造函数块分开定义匿名内部class?
例如,在我的代码中,我希望方法 2 做与方法 1 相同的事情,唯一的区别是方法 2 使用工厂 class 创建 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
}
}
我不想在工厂中声明匿名内部 class class,是否有任何 lambda 表达式允许我将它放在 method2 中?
是的,你可以这样做:
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, (e, 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, final ErrorHandller errorHandller) 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) {
errorHandller.handleError(e, action);
}
};
}
interface ErrorHandller {
void handleError(SQLException e, String action);
}
}
...
如您所见,添加了新界面 ErrorHandller
。另外 Factory::createResultSet
现在接收 ErrorHandller
的实例作为第二个参数。
然后在 Demo::method2
中,我们将 lambda 作为 Factory.createResultSet
方法的第二个参数传递。
您可以创建另一个 Factory
方法,除了 String sql
之外还采用 BiConsumer
。像这样:
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);
}
};
}
}
然后你的 method2
应该是:
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();
}
}
如何与构造函数块分开定义匿名内部class?
例如,在我的代码中,我希望方法 2 做与方法 1 相同的事情,唯一的区别是方法 2 使用工厂 class 创建 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
}
}
我不想在工厂中声明匿名内部 class class,是否有任何 lambda 表达式允许我将它放在 method2 中?
是的,你可以这样做:
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, (e, 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, final ErrorHandller errorHandller) 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) {
errorHandller.handleError(e, action);
}
};
}
interface ErrorHandller {
void handleError(SQLException e, String action);
}
}
...
如您所见,添加了新界面 ErrorHandller
。另外 Factory::createResultSet
现在接收 ErrorHandller
的实例作为第二个参数。
然后在 Demo::method2
中,我们将 lambda 作为 Factory.createResultSet
方法的第二个参数传递。
您可以创建另一个 Factory
方法,除了 String sql
之外还采用 BiConsumer
。像这样:
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);
}
};
}
}
然后你的 method2
应该是:
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();
}
}