【问题标题】:How to use the object initialized in a constructor in other methods of the class如何在类的其他方法中使用构造函数中初始化的对象
【发布时间】:2015-10-30 12:25:14
【问题描述】:

这里是编程新手。我正在使用 Swing、JDBC(Oracle) 创建一个简单的登录应用程序。它在大多数情况下按预期工作。该应用程序有 3 个类 - Logic、UI 和 DBConnection。

请参考这里的完整代码:Full Code

1. LoginLogic.java

    public class LoginLogic {

    LoginUI lu;

    public LoginLogic() {
        lu = new LoginUI();

    }

    public LoginLogic(ResultSet rs) {
        process(rs);
    }

    private void process(ResultSet rs) {
        try {
            if (rs.next()) {
                lu.loginSuccess();

            } else {
                lu.loginFailed();
            }
        } catch (SQLException e) {
            // TODO: handle exception
        }
    }

    public static void main(String[] args) {

        new LoginLogic();

    }


 }

最初,我直接显示了一个 JOptionPane 来代替 loginSuccess() 和 loginFailed() 方法,它按预期工作。但我想将所有 UI 功能委托给 UI 类,所以我在 UI 类中创建了这两个方法

void loginSuccess() {
        JOptionPane.showMessageDialog(null, "Login Successful!");
}

void loginFailed() {
    JOptionPane.showMessageDialog(null, "Login Failed!");
} 

但是这些方法并没有被我在构造函数中创建的 UI 对象调用。没有错误,但也没有 JOptionPane。

如何在 process() 方法中使用 UI 对象引用 lu 来调用 UI 类的方法?

【问题讨论】:

  • 你的做法在我看来不错。您是否尝试使用调试器?你也应该为 TODO 做点什么,也许有一个 SQLException 而你因为 TODO 而看不到它
  • 你有两个构造函数,但你只调用第一个(不带参数)。你怎么打电话给LoginLogic(ResultSet rs)
  • 我现在已经更新了问题,并提供了指向整个代码的链接,应该消除对调用的混淆。

标签: java swing object constructor


【解决方案1】:

正如 JB Nizet 所解释的,您的代码需要进行一些更改。试试下面的代码(它对我有用)。

public class LoginLogic {

LoginUI lu;

public LoginLogic() {
    lu = new LoginUI();

}

public LoginLogic(ResultSet rs) {
    lu = new LoginUI();
    process(rs);
}

private void process(ResultSet rs) {
    try {
        if (rs.next()) {
            lu.loginSuccess();

        } else {
            lu.loginFailed();
        }
    } catch (SQLException e) {
        // TODO: handle exception
    }
}

public static void main(String[] args) {

    /*/ Here you shld get your result rs first 

            con is your Connection object
            Statement stmt = con.createStatement(
            ResultSet.TYPE_SCROLL_INSENSITIVE,
            ResultSet.CONCUR_UPDATABLE);

            ResultSet rs = stmt.executeQuery("SELECT yourColumn FROM yourTable");
    //*/

    new LoginLogic(rs);
}
}

已编辑

根据我们的 cmets,问题在于您正在创建一个新对象:

 private void getConn(String uname, String pwd) {
    ...
        // 4. Process the result set
        new LoginLogic(rs);

    ...

}

这意味着您没有在 if() 语句中调用正确的对象。您的新对象是使用参数化构造函数构造的,该构造函数不会初始化 lu 或更新它。

EDITED2

我认为你必须稍微改变你的设计。我认为以下内容对您有用,但您必须处理异常情况。

public class LoginLogic {

LoginUI lu;

public LoginLogic() {
    lu = new LoginUI();

}


public void process() {
    try {
        if (lu.getRs().next()) {
            lu.loginSuccess();

        } else {
            lu.loginFailed();
        }
    } catch (SQLException e) {
        // TODO: handle exception
    }
}

public static void main(String[] args) {

    LoginLogic loginLogic = new LoginLogic();
    loginLogic.process();
 }
 }

loginUI 将变为:

public class LoginUI {

      ...
       ResultSet rs;

       public ResultSet getRs() {
          return rs;
       }
       ...
      btnLogin.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {

            try {
                String uname = tfUname.getText().trim();
                String pwd = tfPwd.getText().trim();

                LoginDbConn loginDbConn = new LoginDbConn(uname, pwd);// startDB after user presses     
                rs = loginDbConn.getConn();

            } catch (Exception ex) {
                // TODO: handle exception
            }

        }
    });

    ....
 }

LoginDbConn 是这样的:

 public class LoginDbConn {

String uname;
String pwd;
ResultSet rs;
/*
 * public LoginDbConn() { // TODO Auto-generated constructor stub }
 */

public LoginDbConn(String uname, String pwd) {
    this.uname = uname;
    this.pwd = pwd;
}

public ResultSet getConn() {
    try {
        // 0. Register the JDBC drivers
        String driverClass = "oracle.jdbc.driver.OracleDriver";
        Class.forName(driverClass);
        // or DriverManager.registerDriver(new oracle.jdbc.OracleDriver());

        // 1. Get a connection to the Database
        String dbUrl = "jdbc:oracle:thin:@localhost:1521:xe";
        String dbuname = "scott";
        String dbpwd = "tiger";
        Connection conn = DriverManager.getConnection(dbUrl, dbuname, dbpwd);

        // 2. Create a statement
        // String sql = "SELECT * FROM users WHERE name = '"+uname+"' and
        // password = '"+pwd+"'";
        // Statement st = conn.createStatement();
        String sql = "select * from users where name = ? and password = ?";
        PreparedStatement pst = conn.prepareStatement(sql);

        pst.setString(1, uname);
        pst.setString(2, pwd);

        // 3. Execute SQL query
        rs = pst.executeQuery();

        // 5. Close Connection
        // conn.close();

        return rs;
    } catch (SQLException | ClassNotFoundException e) {

            // THIS EXCEPTION MUST ABSOLUTELY BE HANDLED
    }
    return rs;
}

}

希望这会有所帮助(如果有,请为答案投票)。

【讨论】:

  • 这不是我对代码的期望。我在主要问题中添加了指向整个代码的链接。 SQL 查询正在另一个类中处理。我只想在 process() 方法中使用 'lu' 引用,怎么做?
  • 我建议您在每个方法的开头使用断点进行调试,以便您能够查明您的问题。
  • +Guizmoo03 :我知道问题出在哪里。通过 lu 对 loginSuccess() 的调用未完成。我用 println() 替换了 loginSuccess() 并且它有效。所以问题出在通话中。但我不知道如何解决它!
  • 如果您可以 println() 来自 if() 语句的任何内容,这意味着您的 lu 对象有问题,请在调试时检查其值(可能为 null)。这是我唯一想到的问题
  • +Guizmoo03: Yes lu 在调试器中为空。我在第二个构造函数的 process(rs) 处设置断点。我不确定为什么它可能为 null,因为我已经在第一个构造函数中对其进行了初始化。
【解决方案2】:

您的 main 方法调用无参数构造函数。这个无参数构造函数实现为

lu = new LoginUI();

所以它创建了 LoginUI 对象,但什么也不做。特别是,它从不调用 process() 方法,该方法是显示 JOptionPane 的方法。

另一个你从不调用的构造函数确实调用了process() 方法。但它不会初始化 LoginUI 对象。

我也看不出如何调用process() 方法,因为在创建该方法需要作为参数的 ResultSet 的代码中没有任何内容。

【讨论】:

  • 对不起,我没有把整个代码放在这里。第二个构造函数由传递 ResultSet 的 DB 类调用。
【解决方案3】:

您可以通过一个构造函数来实现这一点,而不是使用两个构造函数:

public LoginLogic(ResultSet rs) {
    lu = new LoginUI();
    process(rs);
}

你刚刚从你想调用的地方调用了这个。您可以拨打此电话new LoginLogic(resultSet);

【讨论】:

  • 我认为我最好将整个代码粘贴到这里。这正在制造混乱。我实际上有 3 节课。为了简单起见,我在这里给出了唯一一个类的代码。
  • 也可以通过调用单次来完成。
【解决方案4】:

感谢+Guizmoo03 指出问题的根源。

正如您在这段代码中看到的,该类有 2 个构造函数。以 null 开头的 LoginUI 对象引用在创建 UI 时首先由默认构造函数初始化。

public class LoginLogic {

    LoginUI lu;

    public LoginLogic() {
        lu = new LoginUI();

    }
     .....

但是当将要处理的ResultSet传递给参数化构造函数时,又在DbConn类中创建了一个Logic类的对象。此实例化取消引用 UI 对象变量 lu。因此,正如我在最初的问题中指出的那样,它不能再用于访问 process() 方法中的 UI 类的方法。

...

LoginUI lu;

...

public LoginLogic(ResultSet rs) {
        process(rs);
    }

    private void process(ResultSet rs) {
        try {
            if (rs.next()) {
                lu.loginSuccess();

            } else {
                lu.loginFailed();
            }
        } catch (SQLException e) {
            // TODO: handle exception
        }
    }
...

DbConn 类 sn-p

// 4. Process the result set
   new LoginLogic(rs);

所以解决方案: 一种可能的解决方法是在构造函数之外实例化 UI 对象变量 lu

...
LoginUI lu = new LoginUI();

public LoginLogic() {

}

public LoginLogic(ResultSet rs) {
    process(rs);
}

private void process(ResultSet rs) {
...

虽然这解决了取消引用问题,但当 DbConn 创建逻辑类的新对象时,它会导致 GUI 重新初始化。

public class LoginUI {

        // Container declarations
        ...

        // Component declarations
       ...

        public LoginUI() {
            createFrame();
        }

        private void createFrame() {
        ...

另一个实际上没有太多副作用的解决方法是使用静态方法。但在 OO 代码中使用过多的静态元素并不是一个好习惯。

于是我切换到Singleton pattern with Eager initialization,有效解决了问题。

登录逻辑

public class LoginLogic {

    static final LoginUI lu = LoginUI.getInstance(); // immutable singleton
                                                        // object reference

    public LoginLogic() {
        // TODO Auto-generated constructor stub
    }

    public LoginLogic(ResultSet rs) { // parameterized constructor
        process(rs);
    }

    void process(ResultSet rs) {...

登录界面

public class LoginUI {

    // Container declarations

    // Component declarations

    private static final LoginUI lu = new LoginUI(); // immutable singleton
                                                        // object

    private LoginUI() { // prevent external instantiation
        initUI();
    }

    static LoginUI getInstance() { // getter for the singleton object
        return lu;
    }...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-28
    • 2016-01-06
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    相关资源
    最近更新 更多