Java 是从内部类中访问的,需要声明为final

Java 是从内部类中访问的,需要声明为final,java,sql,prepared-statement,inner-classes,Java,Sql,Prepared Statement,Inner Classes,在上面的代码中,如果我从用于设置PreparedStatement的一个变量中删除final,则表示“”是从内部类中访问的,需要声明为final 我知道java警告我声明final,所以我不能稍后更改变量并中断PreparedStatementCreater,我刚刚创建了一个实例。我在stackoverflow上读过类似的主题,但我还是不明白。我检查了函数ps.setInt,它的参数类型为int。所以它们是按值传递的。无论如何,我都无法更改它们的值。我真不明白为什么我在这里被警告。你能帮我理解吗

在上面的代码中,如果我从用于设置
PreparedStatement
的一个变量中删除final,则表示
“”是从内部类中访问的,需要声明为final

我知道java警告我声明final,所以我不能稍后更改变量并中断PreparedStatementCreater,我刚刚创建了一个实例。我在stackoverflow上读过类似的主题,但我还是不明白。我检查了函数
ps.setInt
,它的参数类型为
int
。所以它们是按值传递的。无论如何,我都无法更改它们的值。我真不明白为什么我在这里被警告。你能帮我理解吗?

这里根本没有传递任何东西(就编译器抱怨的变量而言),而且在Java中所有东西都是按值传递的,不管是引用值还是原语值

问题在于,您试图在匿名内部类中使用外部作用域中的局部变量——除非该变量是
final
,至少在Java 7中是这样。对于Java8,您会发现这是可行的,因为变量实际上是最终的——您无法在外部范围或内部范围内更改变量的值


至于为什么匿名内部类主体中使用的局部变量必须是最终的——据我所知,这是为了避免混淆——并且可能有助于实现的简单性。完全可以设计一种语言,其中闭包中的变量可以是可变的(例如C#可以),但是Java的模型创建了匿名内部类的实例,其中包含匿名内部类主体中使用的所有变量的副本。这很容易理解(您无法观察到任何更改,因为您不允许进行任何更改),这意味着您不会只为了保存外部范围中使用的变量而生成额外的类

它与
PreparedStatement
无关。在匿名类中使用该变量,这就是为什么它必须是final。阅读了解更多信息。这基本上是为了阻止我认为我可以在外部范围内更改内部类变量的值吗?@Ozum:或者实际上是相反的方式。
        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;