【问题标题】:Force static block to be executed before start() method强制在 start() 方法之前执行静态块
【发布时间】:2016-12-04 17:33:59
【问题描述】:

我在我的项目中使用 JavaFX,我有两个类 - MainApp 类和 Database 类。

非常简化的实现如下所示:

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

仅Database类实现的相关部分如下(注意我已经声明并实现了出现在提到的方法中的变量,为了保持代码简短,我只是不在这里粘贴它们)

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

 }

我收到空指针异常是因为:Database 类中的静态块在重写 start() 方法后执行。因此,当我访问数据库类的属性时,它们还没有被初始化。

有没有办法在启动方法之前强制调用静态块?我选择了错误的方法吗?我应该在 start() 方法之外的其他地方开始使用数据库吗?

【问题讨论】:

    标签: java javafx static-block


    【解决方案1】:

    我收到空指针异常是因为:数据库类中的静态块在重写 start() 方法后执行。因此,当我访问 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 类。

    顺便说一句:如果您需要在Applicationstart 方法运行之前初始化某些内容,则应该在应用程序类的覆盖init() method 中完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-11
      • 2018-09-16
      • 2012-04-24
      • 1970-01-01
      • 2017-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多