简体   繁体   中英

is accessed from within inner class, needs to be declared final

        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;

In the code above, if I remove final from one of the variables that I use to set PreparedStatement , it says "" is accessed from within inner class, needs to be declared final .

I understand java warns me to declare final, so I cannot change the variable later and break PreparedStatementCreater of which I just made an instance. I have read similar topics in stackoverflow, however I still cant understand it. I checked the function ps.setInt , its arguments are of type int . So they are passed by value. There is just no way I can change the value of them anyway. I really dont understand why I am getting warned here. Can you help me understand ?

There's nothing being passed here at all (in terms of the variables that the compiler complains about) - and everything is passed by value in Java anyway, whether that's a reference or primitive value.

The problem is that you're trying to use a local variable from an outer scope within an anonymous inner class - and you just can't do that unless the variable is final , at least up and including to Java 7. As of Java 8, you'd find this would work because the variable would be effectively final - you just wouldn't be able to change the value of the variable either in the outer scope or the inner scope.

As for why local variables used within the body of an anonymous inner class have to be final - it's to avoid confusion, as far as I can tell - and possibly to aid simplicity of implementation. It's entirely possible to design a language where variables in closures can be mutable (C# does for example), but Java's model creates an instance of the anonymous inner class with a copy of all the variables that are used within the body of the anonymous inner class. That's simple to understand (you can't observe any changes because you're not allowed to make any) and it means you don't end up with extra classes being generated just to hold variables which are used in the outer scope.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM