类成员用作try-with-resources资源提示非有效final,求原因及解决方案
问题解答
第一个代码报错的原因
try-with-resources要求资源变量必须是final或者等效final——简单来说就是变量初始化后,整个代码逻辑里不能再有对它的赋值操作。你的第一个代码里,m_myResource是类成员变量,编译器没法保证它不会被其他方法、其他线程修改,哪怕你在doTraining里只赋值了一次,它也不符合等效final的要求,所以编译器直接报错。
第二个修改方式的潜在风险
你改后的代码虽然加了本地变量newResource,但try块里用的还是类成员m_myResource,这里有两个明显的坑:
- 要是
Manager在多线程环境下使用,其他线程可能在try块执行期间修改m_myResource的值,导致try-with-resources最终关闭的资源和你实际业务中使用的不是同一个实例。 - 就算是单线程场景,以后如果有人修改
doTraining方法,在try块内部对m_myResource重新赋值,也会破坏逻辑——try-with-resources只会关闭它一开始绑定的那个资源实例,新赋值的资源不会被自动关闭。
正确的写法参考
如果既要把资源存为类成员,又想用try-with-resources自动关闭,应该这么写:
class Manager { MyResource m_myResource; ... void doTraining() { try(MyResource newResource = createMyResource()) { m_myResource = newResource; // 这里编写业务逻辑 ... } } }
但要注意:try块结束后,newResource会被自动关闭,此时m_myResource引用的是一个已经关闭的资源,后续代码如果再调用这个类成员,肯定会触发资源已关闭的异常。
如果你的真实需求是资源不需要在try块结束后关闭,那try-with-resources根本不适合这个场景,不如自己手动管理资源的生命周期,在合适的时机调用close()方法。
内容的提问来源于stack exchange,提问作者lightrek
相关产品推荐
相关产品推荐

