You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java getCoordinates方法try/catch结构优化咨询

问题说明

现有一个从慢加载页面拉取坐标的方法,功能可正常运行,但代码结构(尤其是try/catch部分)存在较多可优化点,原实现代码如下:

public void getCoordinates(){
        EventQueue.invokeLater(() -> loadingLabel.updateCoordinates(true));
        consolePanel.getConsole().append("\nRetrieving coordinates from server\n");
        shapes.clear();

        URL url = null;
        try {
            url = new URL("http://TestServlet/");
        } catch (MalformedURLException e) {
            e.printStackTrace();
            consolePanel.getConsole().append(e.toString());
        }
        try {
            URLConnection connection = url.openConnection();
            connection.setConnectTimeout(1000);
            try (InputStream dataSource = url.openStream()) {

                BufferedReader inputStream = new BufferedReader(new InputStreamReader(
                        dataSource, StandardCharsets.ISO_8859_1));
                double xCoordinate;
                double yCoordinate;
                String line;

                while ((line = inputStream.readLine()) != null) {
                    if(!line.startsWith("#")) {
                        consolePanel.getConsole().append(line + "\n");
                        String[] text =  line.split(",");

                        xCoordinate = Double.parseDouble(text[0]);
                        yCoordinate = Double.parseDouble(text[1]);

                        xCoordinate = Math.abs(xCoordinate)/4;
                        yCoordinate = Math.abs(yCoordinate)/4;

                        String name = text[2];

                        shapes.add(this.mapPanelState.getNewShape(xCoordinate, yCoordinate, 10, name));
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            consolePanel.getConsole().append(e.toString());
        }
        EventQueue.invokeLater(this::repaint);
        EventQueue.invokeLater(() -> loadingLabel.updateCoordinates(false));
    } 
具体优化点
  • 修复空指针风险,合并冗余try/catch:MalformedURLException本身是IOException的子类,不需要单独拆分try块。原代码如果URL初始化失败,url变量为null,后续执行url.openConnection()会直接抛出未捕获的空指针异常,加载状态会永远停留在加载中。
  • 修复超时配置不生效的bug:原代码创建了URLConnection对象并设置了1000ms连接超时,但后续直接调用url.openStream()获取流,根本没有用到配置好超时参数的connection对象,等于超时设置完全无效,这也是慢页面加载时程序长时间无响应的核心原因。另外需要同时设置读取超时,避免服务端响应慢时连接一直挂起。
  • 完善资源自动管理:原代码只把InputStream放进了try-with-resources,外层包装的InputStreamReader、BufferedReader没有纳入自动关闭范围,极端场景下会出现IO句柄泄漏,所有实现了AutoCloseable接口的流对象都应该放到try-with-resources的声明中统一释放。
  • 避免阻塞UI线程:原代码的网络请求、流读取、数据解析全在调用线程执行,如果是在Swing的事件dispatch线程中调用该方法,会直接阻塞UI渲染导致界面卡死。应该把所有IO、计算逻辑放到后台工作线程执行,只有更新控件、写控制台、触发重绘这类UI操作才通过EventQueue.invokeLater切回UI线程执行。
  • 增加坏数据兜底逻辑:原代码直接读取split后数组的固定下标、直接解析数字,如果服务端返回的行缺字段、坐标值不是合法数字,会抛出未捕获的ArrayIndexOutOfBoundsException或NumberFormatException,直接中断整个拉取流程。需要增加格式校验和局部异常捕获,跳过无效行即可,不需要让整个流程崩溃。
  • 保证状态兜底:原代码只有流程正常走到最后才会关闭加载状态、触发重绘,一旦中间抛出未捕获异常,加载动画会一直转。需要把状态重置的逻辑放到finally块中,无论请求成功、失败还是抛异常,都能正常恢复UI状态。
优化后参考代码
public void getCoordinates(){
    // UI操作统一在事件线程执行
    EventQueue.invokeLater(() -> {
        loadingLabel.updateCoordinates(true);
        consolePanel.getConsole().append("\nRetrieving coordinates from server\n");
    });
    shapes.clear();

    // 网络IO与数据解析放后台线程,避免卡UI
    new Thread(() -> {
        try {
            URL url = new URL("http://TestServlet/");
            URLConnection connection = url.openConnection();
            // 同时设置连接超时和读取超时
            connection.setConnectTimeout(1000);
            connection.setReadTimeout(5000);

            // 所有流资源统一自动管理
            try (InputStream dataSource = connection.getInputStream();
                 InputStreamReader isr = new InputStreamReader(dataSource, StandardCharsets.ISO_8859_1);
                 BufferedReader inputStream = new BufferedReader(isr)) {

                String line;
                while ((line = inputStream.readLine()) != null) {
                    if (line.startsWith("#")) {
                        continue;
                    }
                    consolePanel.getConsole().append(line + "\n");
                    String[] text = line.split(",");
                    // 校验行格式合法性
                    if (text.length < 3) {
                        consolePanel.getConsole().append("跳过无效数据行: " + line + "\n");
                        continue;
                    }
                    try {
                        double xCoordinate = Math.abs(Double.parseDouble(text[0])) / 4;
                        double yCoordinate = Math.abs(Double.parseDouble(text[1])) / 4;
                        String name = text[2];
                        shapes.add(this.mapPanelState.getNewShape(xCoordinate, yCoordinate, 10, name));
                    } catch (NumberFormatException e) {
                        consolePanel.getConsole().append("坐标格式错误,跳过行: " + line + "\n");
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            EventQueue.invokeLater(() -> consolePanel.getConsole().append("坐标拉取失败: " + e + "\n"));
        } finally {
            // 无论成功失败,最终都重置UI状态
            EventQueue.invokeLater(() -> {
                repaint();
                loadingLabel.updateCoordinates(false);
            });
        }
    }).start();
}

内容的提问来源于stack exchange,提问作者Mr.Gomer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 13:36:18