在Java中创建一个静态字段final

时间:2014-02-08 09:17:30

标签: java jdbc static jndi final

查看以下代码片段,给出的方案是从Tomcat服务器中的数据库连接池获取数据库连接。

public final class DatabaseConnection {

    private static DataSource dataSource;

    static {
        try {
            Context initContext = new InitialContext();
            Context context = (Context) initContext.lookup("java:comp/env");
            dataSource = (DataSource) context.lookup("jdbc/assignment_db");
        } catch (NamingException e) {
            Logger.getLogger(DatabaseConnection.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
}

我想在课程final中创建唯一的字段。如果我将其设为final字段,那么编译器会抱怨,

  

变量dataSource可能尚未初始化。

在使它成为final之后,如果它在声明位置被初始化为null,则严格禁止在try块中进一步初始化该字段,从而导致编译错误,< / p>

  

无法为最终变量dataSource赋值。

NamingException是一个经过检查的例外。因此,必须抓住或宣布它被抛出。


早些时候,情况有所不同。策略是使用Apache DBCP如下。

public final class DatabaseConnection {

    private static final BasicDataSource basicDataSource;

    static {
        basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3306/assignment_db");
        basicDataSource.setUsername("Tiny");
        basicDataSource.setPassword("root");
    }

    public static Connection getConnection() throws SQLException {
        return basicDataSource.getConnection();
    }
}

其中,该字段可以声明为final,因为没有经过检查的异常,并且try...catch是不必要的。

我可以以某种方式使dataSource最终成为第一种情况吗?

1 个答案:

答案 0 :(得分:2)

这让我陷入了很多次,直到我找到了解决方法。您可以在static块中使用临时变量,并使用该变量在dataSource结束后分配try-catch

private static final DataSource dataSource;

static
{
    DataSource tempDataSource = null;
    try
    {                
        Context initContext = new InitialContext();
        Context context = (Context) initContext.lookup("java:comp/env");
        tempDataSource = (DataSource) context.lookup("jdbc/assignment_db");
    } catch (NamingException ex) {
        Logger.getLogger(DatabaseConnection.class.getName()).log(Level.SEVERE, null, ex);
    }
    dataSource = tempDataSource;
}

但是,我不想正常关注,只有在catch未初始化时才从dataSource块抛出异常,在这种情况下,您不需要局部变量:

static
{
    try
    {                
        Context initContext = new InitialContext();
        Context context = (Context) initContext.lookup("java:comp/env");
        dataSource = (DataSource) context.lookup("jdbc/assignment_db");
    } catch (NamingException ex) {
        Logger.getLogger(DatabaseConnection.class.getName()).log(Level.SEVERE, null, ex);
        throw new ExceptionInInitializerError("dataSource not initialized");
    }
}