Final关键字,并在java中将连接对象声明为Final

Final关键字,并在java中将连接对象声明为Final,java,connection,Java,Connection,我必须将java.sql.Connection对象传递给匿名内部类,这意味着我必须对它进行final引用。然而,我担心任何资源泄漏 public static String foo(final Connection conn){ ... @Override public String call() { ... return runner.query(connection, sql, scalarHandler); } } 我无法理

我必须将
java.sql.Connection
对象传递给匿名内部类,这意味着我必须对它进行
final
引用。然而,我担心任何资源泄漏

public static String foo(final Connection conn){
    ...
    @Override
    public String call() {
        ...
        return runner.query(connection, sql, scalarHandler);
    }
}

我无法理解
final
关键字的内部工作原理。它实际上是如何密封对象以使其不能更改为引用另一个对象的?将
连接
对象声明为
最终
安全吗

使某个东西
最终
不会影响它的泄漏趋势-也许你把它与
静态
混淆了,后者(有时)会

<声明>代码< >最终只是意味着一旦设置它就不会改变——事实上,如果编译器包含可以更改的代码,编译器会认为它是一个错误。


标记参数和变量
final
,以便可以从内部/匿名类访问它们,这只是一个技巧,可以满足匿名类的一些奇怪需求。实际上,有人说,如果参数在初始化后从未更改过,就可以自动将其视为
final
,以避免在这种情况下标记它们。

制作一些
final
不会影响它的泄漏趋势-也许你把它与
静态
混淆了,这可能会导致(有时)

<声明>代码< >最终只是意味着一旦设置它就不会改变——事实上,如果编译器包含可以更改的代码,编译器会认为它是一个错误。

标记参数和变量
final
,以便可以从内部/匿名类访问它们,这只是为了满足匿名类的一些奇怪要求而采取的一种伎俩。实际上,有人说,如果参数在初始化后从未更改过,则会自动将其视为
final
,以避免需要o在这种情况下标记它们

它实际上是如何密封对象以使其不能更改为引用另一个对象的

小心--
final
是对象引用的修饰符。因此
final
会“密封”引用,而不是对象

这种“密封”有两种方式。一种是通过编译器检查所有
final
变量和字段。来自Java语言规范:

如果将最终变量赋值给,则这是一个编译时错误,除非在赋值之前明确未赋值

空的最终类变量必须由 声明它的类,或发生编译时错误

一个空的最终实例变量必须在声明它的类的每个构造函数的末尾被明确地赋值,否则会发生编译时错误

另一种方法是JVM在类加载时进行字节码验证。
putfield
putstatic
字节码指令抛出
IllegalAccessError
s,如果操作的字段是
final
,并且字节码指令没有出现在特定位置

但是,在这里您必须小心一点,
final
关键字只会“粘住”字段。临时变量和参数在编译时会丢失其
final
-属性,因此,如果您使用不兼容的编译器或使用字节码操作,JVM只能验证字段的
final
-属性


连接
对象声明为final是否安全

我不完全确定您所说的“安全”是什么意思,但如果您说的是“不会在程序中导致错误”,那么在很大程度上是的(多线程和/或编译时常量的存在可能会改变这个答案,也可能不会改变这个答案)。如果您将
final
放在引用上,并且您的程序已编译,则您的程序应完全按照其工作方式工作

它实际上是如何密封对象以使其不能更改为引用另一个对象的

小心--
final
是对象引用的修饰符。因此
final
会“密封”引用,而不是对象

这种“密封”有两种方式。一种是通过编译器检查所有
final
变量和字段。来自Java语言规范:

如果将最终变量赋值给,则这是一个编译时错误,除非在赋值之前明确未赋值

空的最终类变量必须由 声明它的类,或发生编译时错误

一个空的最终实例变量必须在声明它的类的每个构造函数的末尾被明确地赋值,否则会发生编译时错误

另一种方法是JVM在类加载时进行字节码验证。
putfield
putstatic
字节码指令抛出
IllegalAccessError
s,如果操作的字段是
final
,并且字节码指令没有出现在特定位置

但是,在这里您必须小心一点,
final
关键字只会“粘住”字段。临时变量和参数在编译时会丢失其
final
-属性,因此,如果您使用不兼容的编译器或使用字节码操作,JVM只能验证字段的
final
-属性


连接
对象声明为final是否安全


我不完全确定您所说的“安全”是什么意思,但如果您说的是“不会在程序中导致错误”,那么在很大程度上是的(多线程和/或编译时常量的存在可能会改变这个答案,也可能不会改变这个答案)。如果您将
final
放在引用上,并且您的程序已编译,则您的程序应完全按照其工作方式运行。

安全吗?这取决于您对
public void test() {
    Connection conn = null;
    try {
        conn = DBUtils.createConnection(dataSource);
        foo(conn);
    } finally {
        DBUtils.close(conn);
    }

}

public void foo(final Connection conn) {
    MessageBox messageBox = getMessageBox("You want to update Foo?");
    messageBox.setCallBackHandler(new MessageCallback() {

        @Override
        public void yesClicked() {
                try {
                   updateFooTable(conn); //conn could be closed
                } catch (SQLException e) {
                    throw new RuntimeException(e.getMessage(), e);
                }
        }
        });
    messageBox.display();
}