简体   繁体   English

Java匿名内部类声明

[英]Java anonymous inner class declaration

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. 例如,在我的代码中,我希望method2与method1做相同的事情,唯一的区别是method2使用Factory类创建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? 我不想在Factory类中声明匿名内部类,是否有任何lambda表达式允许我将其放入method2中?

Yes, you can do something like this: 是的,您可以执行以下操作:

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);
    }
}

...

As you can see, new interface ErrorHandller was added. 如您所见,添加了新接口ErrorHandller Also Factory::createResultSet receive instance of ErrorHandller as second argument now. 另外Factory::createResultSet现在将ErrorHandller实例作为第二个参数接收。 And then in Demo::method2 we pass lambda as the second argument of Factory.createResultSet method. 然后在Demo::method2 ,将lambda传递为Factory.createResultSet方法的第二个参数。

You can create another Factory method that takes a BiConsumer in addition to the String sql . 除了String sql之外,您还可以创建另一个采用BiConsumer Factory方法。 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: 然后您的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();
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM