简体   繁体   English

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

[英]Making a static field final in Java

Looking at the following code snippet, the scenario given is about fetching a database connection from a database connection pool in the Tomcat Server. 查看以下代码片段,给出的方案是从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();
    }
}

I would like making the only field in the class final . 我想成为班级final唯一的一个领域。 If I make it a final field then, the compiler complains, 如果我把它作为final字段,那么编译器会抱怨,

variable dataSource might not have been initialized. 变量dataSource可能尚未初始化。

After making it final , if it is initialized to null at the declaration place then, further initialization of this field in the try block is severely forbidden causing a compilation error, final完成后,如果在声明位置将其初始化为null ,则严禁禁止在try块中进一步初始化此字段,从而导致编译错误,

cannot assign a value to final variable dataSource. 无法为最终变量dataSource分配值。

NamingException is a checked exception. NamingException是一个经过检查的异常。 Hence, it must be caught or declared to be thrown. 因此,它必须被捕获或声明被抛出。


Earlier, there was a different scenario. 早些时候,情况有所不同。 The strategy was to use Apache DBCP as follows. 策略是使用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();
    }
}

In which, the field could be declared final because there is no checked exception and try...catch is unnecessary. 其中,该字段可以被声明为final因为没有检查异常并且try...catch是不必要的。

Can I somehow make dataSource final as in the first case? 在第一种情况下,我能以某种方式使dataSource最终的吗?

This has got me stuck many times, until I found out a workaround. 这让我陷入了很多次,直到找到了解决方法。 You can use a temporary variable in the static block, and assign the dataSource after try-catch ends using that variable: 您可以在static块中使用临时变量,并在try-catch结束后使用该变量分配dataSource

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

However, I would rather not follow normally, and throw the exception from the catch block only if dataSource is not initialized, in which case, you won't need a local variable: 但是,我不想正常关注,只有在未初始化dataSource时才从catch块中抛出异常,在这种情况下,您不需要局部变量:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM