我正在为我的项目使用JavaFX,我有两个类 - MainApp 类和数据库类。
非常简化的实现看起来像这样:
public class MainApp extends Application {
@Override
public void start(Stage stage) throws Exception {
// Getting username & password doing some initialization, etc.
Database.setUserName(username);
Database.setPassword(password);
Database.testConnection();
}
// This method was pretty much generated by IDE
public static void main(String[] args)
{
launch(args);
}
}
只有数据库类实现的相关部分如下(注意我已经声明并实现了在提到的方法中出现的变量,我只是不要将它们粘贴在这里以保持代码简短)
public class Database {
private static OracleDataSource dataSource;
static {
try {
dataSource = new OracleDataSource();
dataSource.setURL("myjdbcaddress");
dataSource.setUser(userName);
dataSource.setPassword(password);
System.out.print("Static block executed...");
}
catch (SQLException e)
{
System.out.print("Static block caught...");
throw new ExceptionInInitializerError("Initial Database Connection not established. Sorry.");
}
}
public static Connection getConnection()
{
Connection conn = null;
try
{
conn = dataSource.getConnection();
if (conn != null)
isConnected = true;
}
catch (SQLException e)
{
e.printStackTrace();
}
return conn;
}
}
由于这个原因,我得到空指针异常:数据库类中的静态块在重写 start()方法后执行。因此,当我访问Database类的属性时,它们尚未初始化。
有没有办法在start方法之前强制调用静态块?我选择了错误的做法吗?我应该在 start()方法之外的其他地方开始使用数据库吗?
答案 0 :(得分:1)
由于这个原因,我得到空指针异常:在重写的start()方法之后执行Database类中的静态块。因此,当我访问Database类的属性时,它们尚未初始化。
不,这不是问题。加载类时会执行静态初始化程序,这应该在之前发生(它总是在使用除类中static
常量之外的任何内容之前完成。)
Database.setUserName(username);
或更早。
问题可能是userName
和password
尚未分配(尽管没有更多代码很难分辨)。
我不建议使用static
数据传递信息,而是以允许访问非静态对象的方式设计应用程序,以便在需要的地方与数据库进行通信。
但是,您可以通过将代码从静态初始化程序移动到static
方法来解决您的问题:
public class Database {
private static OracleDataSource dataSource;
public static void login(String userName, String password) {
try {
dataSource = new OracleDataSource();
dataSource.setURL("myjdbcaddress");
dataSource.setUser(userName);
dataSource.setPassword(password);
System.out.print("Static block executed...");
} catch (SQLException e) {
throw new IllegalStateException("Initial Database Connection not established. Sorry.", e);
}
}
...
}
Database.login(username, password);
Database.testConnection();
但同样:尽量避免使用允许从任何地方进行访问的Database
类。
BTW:如果您需要在start
Application
方法运行之前初始化某些内容,则应该在应用程序类的覆盖init()
method中完成。