【问题标题】:Use non-final variable inside inner method using Java使用 Java 在内部方法中使用非最终变量
【发布时间】:2017-10-23 16:35:05
【问题描述】:

我正在使用 Jdbctemplate 并尝试在 mapRow 方法中设置一个布尔值。但它不允许,它说

Cannot refer to a non-final variable isEveryTransactionNotClosed inside an inner class defined in a different method

这是我的代码

public boolean isEveryTransactionNotClosed (String txIds) throws QiibException {
    String sql = "<Query> ";
    logger.info("isEveryTransactionNotClosed SQL :"+sql);
    boolean isEveryTransactionNotClosed = true;
    try {
        isEveryDealNotClosed =  getJdbcTemplate().queryForObject(sql, new Object[] {dealIds}, 
                new RowMapper<Boolean>()  {
                public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
                    if (!rs.next()) {
                        isEveryTransactionNotClosed = false;    -->                         
                    }
                }
        });
    } catch(EmptyResultDataAccessException e) {
        logger.error("Empty result data - isEveryTransactionNotClosed ");   
    }
   return isEveryTransactionNotClosed ;
}

如何在类中使用 isEveryTransactionNotClosed?

【问题讨论】:

  • 通过调用它?你能展示一下你现在是如何称呼它的吗?不要给变量取与方法相同的名称。将您的变量声明为 final 并重试
  • @Stultuske,我将该方法称为 boolean result = isEveryTransactionNotClosed (String dealIds);
  • 您的代码存在一些问题。检查我刚刚发布的答案,然后重试。
  • 如果局部变量不是最终的(或者因为 java 8 有效地最终),您不能将局部变量访问到内部类中

标签: java


【解决方案1】:

您的代码存在一些问题:

    public boolean isEveryTransactionNotClosed (String txIds) throws QiibException {
        String sql = "<Query> ";
        logger.info("isEveryTransactionNotClosed SQL :"+sql);
        try {
            final boolean isEveryDealNotClosed =  getJdbcTemplate().queryForObject(sql, new Object[] {dealIds}, 
                    new RowMapper<Boolean>()  {
                    public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
                        if (!rs.next()) {
                            isEveryTransactionNotClosed = false;    -->                         
                        }
                    }
            });
        } catch(EmptyResultDataAccessException e) {
            logger.error("Empty result data - isEveryTransactionNotClosed ");   
        }
       return isEveryTransactionNotClosed ;
    }

将解决您现在遇到的问题,这将产生两个新问题:

 1. You would try to re-assign a final variable
 2. Your method has a return value Boolean, but doesn't return anything.

将您的代码更改为:

public boolean isEveryTransactionNotClosed (String txIds) throws QiibException {
    String sql = "<Query> ";
    logger.info("isEveryTransactionNotClosed SQL :"+sql);
    boolean isEveryDealNotClosed = true;
    try {
        isEveryDealNotClosed =  getJdbcTemplate().queryForObject(sql, new Object[] {dealIds}, 
                new RowMapper<Boolean>()  {
                public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
                    return rs.next();
                }
        });
    } catch(EmptyResultDataAccessException e) {
        logger.error("Empty result data - isEveryTransactionNotClosed ");   
    }
   return isEveryDealNotClosed;
}

【讨论】:

  • 完美。也详细说明了原因。
  • 那么变量名不匹配 - isEveryTransactionNotClosed vs isEveryDealNotClosed
  • @GyroGearless 是的,一眼看上去就是这样
  • @Stultuske,你错过了一分。 isEveryTransactionNotClosed 应该重命名为 isEveryDealNotClosed 。请更新您的代码
  • @Yakhoob 不错,会的:)
【解决方案2】:

如果您需要最终的可变布尔值,您可以使用AtomicBoolean 代替布尔值。请参阅下面的代码更改。

但是,正如其他人所说,您的代码中还有一些其他错误。您可能还需要对其进行更改才能使其正常工作。

public boolean isEveryTransactionNotClosed (String txIds) throws QiibException {
    String sql = "<Query> ";
    logger.info("isEveryTransactionNotClosed SQL :"+sql);
    // changed line
    final AtomicBoolean isEveryTransactionNotClosed = new AtomicBoolean(true);
    try {
        isEveryDealNotClosed =  getJdbcTemplate().queryForObject(sql, new Object[] {dealIds}, 
                new RowMapper<Boolean>()  {
                public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
                    if (!rs.next()) {
                        // changed line
                        isEveryTransactionNotClosed.set(false);                         
                    }
                }
        });
    } catch(EmptyResultDataAccessException e) {
        logger.error("Empty result data - isEveryTransactionNotClosed ");   
    }
   return isEveryTransactionNotClosed.get();
}

【讨论】:

  • 但您仍在使用 isEveryDealNotClosed (在 try 中,第一个语句)。那应该是 isEveryTransactionNotClosed 吧
  • 我刚刚复制了您的代码并更改了行以说明如何在内部类中使用AtomicBoolean。还有其他错误,例如其他人说您的方法mapRow 必须返回Boolean,必须更改。
【解决方案3】:

Stultuske的解决方案是正确的。但它并没有解释错误的原因。

简短的回答是,您不能在内部类中使用非最终局部变量。它可以是有效的 final (因此它并不需要关键字)。

来自JLS - 8.1.3. Inner Classes and Enclosing Instances

任何使用但未在内部类中声明的局部变量、形参或异常参数都必须声明为 final。

解释您的问题。

不是最终的并且肯定不是有效的最终,因为你的内部类改变了局部变量。

另一种解决方案:

  • 允许内部类访问和修改成员变量,
  • 使用 wrapper 来创建最终的实例来满足你的价值

【讨论】:

  • 我认为您错过了帖子中的一部分:“它不是最终的,而且肯定不是最终的,因为您的内部类是变量”(我假设您的意思是重新分配或更改)?
  • @Stultuske 确实,没有评论那条线...谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多