强制静态块在start()方法之前执行

时间:2016-12-04 17:34:00

标签: java javafx static-block

我正在为我的项目使用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()方法之外的其他地方开始使用数据库吗?

1 个答案:

答案 0 :(得分:1)

  

由于这个原因,我得到空指针异常:在重写的start()方法之后执行Database类中的静态块。因此,当我访问Database类的属性时,它们尚未初始化。

不,这不是问题。加载类时会执行静态初始化程序,这应该在之前发生(它总是在使用除类中static常量之外的任何内容之前完成。)

Database.setUserName(username);

或更早。

问题可能是userNamepassword尚未分配(尽管没有更多代码很难分辨)。

我不建议使用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中完成。