No operations allowed after statement closed.

之所以会出现这个异常,是因为Mysql在5以后针对超长时间DB连接做了一个处理,那就是如果一个DB连接在无任何操作情况下过了8个小时后,Mysql会自动把这个连接关闭。所以使用连接池的时候虽然连接对象还在但是链接数据库的时候会一直报这个异常。解决方法很简单在Mysql的官方网站上就可以找到。 有两个方法
###第一种是在DB连接字符串后面加一个参数。
这样的话,如果当前链接因为超时断掉了,那么驱动程序会自动重新连接数据库。

jdbc:mysql://localhost:3306/makhtutat?autoReconnect=true    

不过Mysql并不建议使用这个方法。因为第一个DB操作失败的后,第二DB成功前如果出现了重新连接的效果。

conn.createStatement().execute(
  "UPDATE checking_account SET balance = balance - 1000.00 WHERE customer='Smith'");
conn.createStatement().execute(
  "UPDATE savings_account SET balance = balance + 1000.00 WHERE customer='Smith'");
conn.commit();

当然如果出现了重新连接,一些用户变量和临时表的信息也会丢失。 ###另一种方法是Mysql推荐的,需要程序员手动处理异常。

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    int retryCount = 5;
    boolean transactionCompleted = false;
    do {
        try {
            conn = getConnection(); // assume getting this from a
                                    // javax.sql.DataSource, or the
                                    // java.sql.DriverManager
            conn.setAutoCommit(false);
            retryCount = 0;
            stmt = conn.createStatement();
            String query = "SELECT foo FROM bar ORDER BY baz";
            rs = stmt.executeQuery(query);
            while (rs.next()) {
            }
            all.close()
            transactionCompleted = true;
        } catch (SQLException sqlEx) {
            String sqlState = sqlEx.getSQLState();
           // 这个08S01就是这个异常的sql状态。单独处理手动重新链接就可以了。
            if ("08S01".equals(sqlState) || "40001".equals(sqlState)) 
                {                
                    retryCount--;            
                 } else {                
                     retryCount = 0;            
                     }        
         } finally {            
                 all close:        
             }    
      } while (!transactionCompleted && (retryCount > 0));}
}
<think>嗯,用户想了解Java中如何遍历List。首先,我得回忆一下Java中的List遍历方法有哪些。常见的应该有三种:for循环、增强for循环和迭代器。可能还有Java 8的Stream API的forEach方法。 然后,我需要考虑用户可能的背景。可能是刚开始学Java,或者对集合操作不太熟悉。需要解释清楚每种方法的用法,给出示例代码,并指出优缺点,这样用户可以根据情况选择合适的方法。 接下来,要确保回答结构清晰。分点说明每种遍历方式,比如1. 普通for循环,2. 增强for循环,3. 迭代器,4. forEach方法。每种方法都需要代码示例,注意要使用正确的语法,比如泛型、变量命名等,可能需要用List<String>作为例子。 还要注意提到线程安全的问题,比如在用迭代器遍历时删除元素会抛异常,而使用CopyOnWriteArrayList或者在迭代器中正确使用remove方法。这点可能对用户在实际开发中遇到问题时有帮助。 另外,Java 8的Stream API的forEach可能用户不太熟悉,需要简单说明,但要指出它在并行处理时的优势。同时提醒顺序问题,避免误解。 需要检查是否覆盖了所有常见的遍历方式,有没有遗漏,比如ListIterator可能不太常用,但如果有必要可以提到,不过可能用户更关注基础方法。不过用户的问题只是“介绍”,所以可能不需要太深入。 确保回答的语言用中文,避免术语错误,比如“迭代器”而不是“迭代器”。代码中的注释也要用中文吗?用户没有特别要求,但可能更易于理解,所以可以保留英文注释,或者简单翻译。 最后,总结一下各种方法的适用场景,帮助用户根据需求选择。比如普通for循环需要索引,增强for代码简洁,迭代器适合边遍历边删除,forEach适合函数式编程。 还要注意用户提到的系统级指令,数学表达式用$...$,但这个问题不涉及数学公式,所以可能不需要处理。但如果有代码块,需要用正确的格式,比如Java代码块标记出来,确保语法正确。 可能用户的问题比较基础,但需要详细说明,特别是异常情况和最佳实践,比如不要在遍历时用List的remove方法,而用迭代器的remove,避免ConcurrentModificationException。 检查是否有错误,比如普通for循环的条件是i < list.size(),对吗?是的,因为索引从0开始。迭代器的hasNext()和next()的使用是否正确。是的。 总结一下,回答的结构应该是先介绍遍历方法,每种方法给出示例,说明优缺点,然后注意事项,最后总结。这样用户能逐步理解,并根据自己的情况选择合适的方法。</think>在 Java遍历 `List` 有以下几种常见方法,以下从基础到进阶逐步说明: --- ### 1. **普通 for 循环** 通过索引遍历,适用于需要操作索引的场景。 ```java List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); for (int i = 0; i < list.size(); i++) { String element = list.get(i); System.out.println(element); } ``` - **优点**:可通过索引访问元素。 - **缺点**:对 `LinkedList` 性能较差(`get(i)` 时间复杂度为 $O(n)$)。 --- ### 2. **增强 for 循环(foreach)** 语法简洁,适用于不需要索引的场景。 ```java for (String element : list) { System.out.println(element); } ``` - **优点**:代码简洁,适用于所有实现 `Iterable` 接口的集合。 - **缺点**:无法直接操作索引,遍历时不能修改集合结构(否则抛出 `ConcurrentModificationException`)。 --- ### 3. **迭代器(Iterator)** 显式使用迭代器,适合需要边遍历边删除元素的场景。 ```java Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); // 安全删除当前元素 if (element.equals("B")) { iterator.remove(); } } ``` - **优点**:支持安全的元素删除操作。 - **缺点**:代码相对冗长。 --- ### 4. **Java 8+ 的 forEach 方法** 结合 Lambda 表达式,实现函数式编程风格。 ```java list.forEach(element -> System.out.println(element)); // 或使用方法引用 list.forEach(System.out::println); ``` - **优点**:代码简洁,支持并行流(`parallelStream()`)。 - **缺点**:无法修改集合外部变量(需使用 `final` 或等效 final 的局部变量)。 --- ### 5. **ListIterator** 双向遍历(仅适用于 `List`),允许向前或向后遍历及修改元素。 ```java ListIterator<String> listIterator = list.listIterator(); while (listIterator.hasNext()) { String element = listIterator.next(); System.out.println(element); } // 反向遍历 while (listIterator.hasPrevious()) { String element = listIterator.previous(); System.out.println(element); } ``` --- ### **注意事项** - **遍历时修改集合**:除通过 `Iterator.remove()` 外,其他修改操作(如 `list.add()` 或 `list.remove()`)会触发 `ConcurrentModificationException`。 - **性能选择**:根据 `List` 实现类选择遍历方式(如 `ArrayList` 适合普通 for 循环,`LinkedList` 适合迭代器)。 - **线程安全**:多线程环境下需使用 `CopyOnWriteArrayList` 或同步机制。 --- ### **总结** | 方法 | 适用场景 | 线程安全 | |--------------------|----------------------------------|------------------| | 普通 for 循环 | 需要索引操作 | 需自行同步 | | 增强 for 循环 | 简单遍历 | 需自行同步 | | 迭代器 | 需要删除元素 | 需自行同步 | | forEach + Lambda | 函数式风格 | 依赖集合实现 | | ListIterator | 双向遍历或修改 | 需自行同步 | 根据具体需求选择合适的方法,优先考虑代码简洁性和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值