簡體   English   中英

如何在類的其他方法中使用在構造函數中初始化的對象

[英]How to use the object initialized in a constructor in other methods of the class

在這里編程新手。 我正在使用Swing,JDBC(Oracle)創建一個簡單的登錄應用程序。 它在大多數情況下都可以正常工作。 該應用程序具有3類-邏輯,UI和DBConnection。

請在此處參考整個代碼: 完整代碼

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類的方法?

您的主要方法調用了無參數構造函數。 此無參數構造函數實現為

lu = new LoginUI();

因此,它創建了LoginUI對象,但僅此而已。 特別是,它永遠不會調用process()方法,該方法顯示JOptionPane。

您從未調用過的另一個構造函數會調用process()方法。 但是它不會初始化LoginUI對象。

我也看不到如何調用process()方法,因為在代碼中沒有任何東西創建該方法需要作為參數的ResultSet。

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

已編輯

根據我們的評論,問題在於您正在以下位置創建一個新對象:

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

    ...

}

這意味着您沒有在if()語句中調用正確的對象。 您的新對象是使用參數化構造函數構造的,該構造函數不會初始化lu或對其進行更新。

編輯2

我認為您必須對設計進行一些更改。 我認為以下內容對您有用,但您必須處理例外情況。

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

}

希望這會有所幫助(如果是,請投票給答案)。

除了使用兩個構造函數,您還可以通過一個構造函數實現此目的:

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

您只是從您要呼叫的地方撥打了此電話。 您可以通過new LoginLogic(resultSet);來調用它new LoginLogic(resultSet);

感謝+ Guizmoo03指出了問題的根源。

如您在此代碼中看到的,該類具有2個構造函數。 創建UI時,默認構造函數首先初始化從null開始的LoginUI對象引用。

public class LoginLogic {

    LoginUI lu;

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

    }
     .....

但是,當Logic類的對象傳遞要處理的ResultSet到參數化構造函數時,將再次在DbConn類中創建該對象。 此實例取消引用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類片段

// 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代碼中使用太多靜態元素不是一個好習慣。

因此,我切換到具有Eager初始化Singleton模式 ,從而有效地解決了該問題。

登錄邏輯

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) {...

登錄UI

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM