实现ActiveMQ的MessageCreator时遭遇编译期错误求助
解决ActiveMQ生产者代码中的编译错误:Cannot refer to non-final local variable
这个问题其实是Java语法规则导致的,和ActiveMQ本身没太大关系,我来给你拆解清楚:
错误原因
Java有个明确规定:如果你在匿名内部类或者Lambda表达式里引用外部方法的局部变量,这个变量必须是final的,或者是「effectively final」(简单说就是变量声明后再也没有被重新赋值过)。
你遇到的错误,就是因为你的messageCount变量在作用域内被修改过(比如做了messageCount++或者messageCount = 10这类操作),导致它不符合这个要求,编译器就会直接报错。
为什么教程里能正常运行?
大概率教程里的messageCount要么被声明成了final,要么从始至终没有被修改过——也就是它是effectively final的,所以编译器允许在匿名类/Lambda里引用它。你回头对照一下教程代码,肯定能发现这个差异。
解决办法
根据你的需求,有几种可行的方案:
- 如果不需要修改messageCount的值
直接把变量声明为final即可:
final int messageCount = 1; // 声明为final,之后不再修改 textMessage.setIntProperty(MSG_COUNT, messageCount);
- 如果需要修改messageCount的值
用一个可变的包装类来封装它,比如java.util.concurrent.atomic.AtomicInteger,它可以在保持引用不变的情况下修改内部的值:
AtomicInteger messageCount = new AtomicInteger(0); // 当需要计数时 messageCount.incrementAndGet(); // 在设置属性时 textMessage.setIntProperty(MSG_COUNT, messageCount.get());
这样即使在匿名类/Lambda里引用,编译器也不会报错,因为messageCount这个引用本身是effectively final的,只是内部的数值可以变化。
- Java 8+的简化小技巧
如果你只是偶尔修改,也可以把messageCount改成一个单元素数组(虽然不如AtomicInteger优雅,但也是常用的应急方案):
int[] messageCount = {0}; // 修改时 messageCount[0]++; // 设置属性时 textMessage.setIntProperty(MSG_COUNT, messageCount[0]);
内容的提问来源于stack exchange,提问作者Manish
相关产品推荐
相关产品推荐

