final int receiverUserId = sendMessageRequest.getReceiverUserId();
final int senderUserId = sendMessageRequest.getSenderUserId();
final int replyTo = sendMessageRequest.getReplyTo();
final int subsiteId = sendMessageRequest.getRelatedSubsiteId();
final String message = sendMessageRequest.getMessage();
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplateObject.update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps =
connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, senderUserId);
ps.setInt(2, receiverUserId);
ps.setInt(3, replyTo);
ps.setInt(4, subsiteId);
ps.setString(5, message);
return ps;
}
},
keyHolder
);
return true;
在上面的代码中,如果我从用于设置 PreparedStatement
的变量之一中删除 final ,它会说 ""从内部类中访问,需要声明为 final
。
我知道java警告我声明final,所以我不能稍后更改变量并破坏我刚刚创建的实例的PreparedStatementCreater。我在 stackoverflow 上读过类似的主题,但我仍然无法理解。我检查了函数ps.setInt
,它的参数是int
类型。所以它们是按值传递的。无论如何我都无法改变它们的值(value)。我真的不明白为什么我会在这里收到警告。你能帮我理解一下吗?
最佳答案
这里根本没有传递任何内容(就编译器提示的变量而言)——无论如何,在 Java 中所有内容都是按值传递的,无论是引用值还是原始值。
问题是,您试图在匿名内部类中使用来自外部作用域的局部变量 - 除非该变量是 final
,否则您无法这样做,至少在 Java 7 之前是这样。从 Java 8 开始,您会发现这可行,因为该变量将实际上是final - 您只是无法在外部作用域或内部作用域中更改变量的值。
至于为什么在匿名内部类的主体中使用的局部变量必须是最终的 - 据我所知,这是为了避免混淆 - 并且可能有助于简化实现。完全可能设计一种语言,其中闭包中的变量可以是可变的(例如,C# 就是这样),但是 Java 的模型创建匿名内部类的实例,其中包含匿名内部类主体中使用的所有变量的副本。这很容易理解(您无法观察到任何更改,因为您不允许进行任何更改),这意味着您最终不会生成额外的类来保存外部作用域中使用的变量。
关于java - 从内部类内部访问,需要声明为final,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27216232/