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

时间:2014-11-30 17:46:38

标签: java sql prepared-statement inner-classes

        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,则会显示"" is accessed from within inner class, needs to be declared final

我理解java警告我声明final,所以我不能稍后更改变量并打破我刚刚创建实例的PreparedStatementCreater。我在stackoverflow中读过类似的主题,但是我仍然无法理解它。我检查了函数ps.setInt,其参数类型为int。所以它们是通过价值传递的。无论如何,我无法改变它们的价值。我真的不明白为什么我会在这里得到警告。你能帮我理解吗?

1 个答案:

答案 0 :(得分:1)

这里根本没有传递(就编译器抱怨的变量而言) - 无论如何,所有内容都是通过Java传递的,无论是' sa参考或原始值。

问题在于您尝试使用匿名内部类中外部作用域的局部变量 - 除非变量为final,否则您无法做到这一点,至少从Java 7开始,你发现这可行,因为变量实际上是最终的 - 你只是无法改变它的价值变量在外部范围或内部范围内。

至于为什么在匿名内部类的主体内使用的局部变量必须是最终的 - 它可以避免混淆,据我所知 - 并且可能有助于简化实施。完全可能设计一种语言,其中闭包中的变量是可变的(例如C#),但Java的模型创建了一个带有<的匿名内部类的实例em>复制在匿名内部类的主体内使用的所有变量。这很容易理解(你不能观察到任何变化,因为你不允许做任何变化)这意味着你不会为了保存变量而生成额外的类。用于外部范围。