2015-10-30 468 views
1

这里编程新手。我正在使用Swing,JDBC(Oracle)创建一个简单的登录应用程序。它大部分都按预期工作。该应用程序有3个类 - 逻辑,用户界面和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对象没有被所谓的这些方法这2种方法。没有错误,但也没有JOptionPane。

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

+0

你的方式看起来好像没什么问题。你尝试使用调试器吗?你也应该为TODO做些什么,也许有'SQLException',你不会看到它,因为TODO –

+0

你有两个构造函数,但你只调用第一个(没有参数)。你如何调用'LoginLogic(ResultSet rs)'? –

+0

我已经通过现在链接到整个代码更新了问题,应该消除关于调用的混淆。 –

回答

3

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

EDITED

根据我们的意见,问题是,你正在创建你的一个新的对象:

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

}

希望这将有助于(如果有的话,请投票给答案)。

+0

这不是我期望的代码。我在主要问题中添加了一个链接到整个代码。 SQL查询正在另一个类中处理。我只是想在process()方法中使用'lu'引用,它如何完成? –

+0

我建议你在每个方法开始时使用断点进行调试,这样你就可以查明你的问题。 – Guizmoo03

+0

+ Guizmoo03:我知道问题出在哪里。通过lu调用loginSuccess()没有完成。我用println()替换了loginSuccess(),它起作用。所以问题在于呼叫。但我不知道如何解决它! –

3

您的主要方法调用no-arg构造函数。这个无参数构造函数实现为

lu = new LoginUI(); 

因此,它创建了LoginUI对象,但没有做任何其他事情。特别是,它永远不会调用显示JOptionPane的方法process()

另一个构造函数,你永远不会打电话,确实调用process()方法。但它不初始化LoginUI对象。

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

+0

对不起,我没有把整个代码放在这里。第二个构造函数由传递ResultSet的DB类调用。 –

2

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

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

你刚才叫这个从那里,你想打电话。你可以这样称呼它new LoginLogic(resultSet);

+0

我想我最好在这里粘贴整个代码。这造成了混乱。我有3个班。为了简单起见,我在这里给出了唯一一个类的代码。 –

+0

您也可以通过调用单一时间来做这件事。 –

1

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

正如你在这段代码中看到的,这个类有2个构造函数。开始为null的LoginUI对象引用在创建UI时由缺省构造函数初始化。

public class LoginLogic { 

    LoginUI lu; 

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

    } 
    ..... 

但是,当它将ResultSet传递给参数化构造函数时,Logic类的一个对象再次在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对象变量构造外部作为这样

... 
LoginUI lu = new LoginUI(); 

public LoginLogic() { 

} 

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

private void process(ResultSet rs) { 
... 

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

public class LoginUI { 

     // Container declarations 
     ... 

     // Component declarations 
     ... 

     public LoginUI() { 
      createFrame(); 
     } 

     private void createFrame() { 
     ... 

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

所以我切换到Singleton pattern with Eager initialization,这有效地解决了这个问题。

LoginLogic

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

LoginUI

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; 
    }... 
相关问题