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

Java空指针异常求助:输入文件非空但flightReader为何为空?

Java空指针异常排查:flightReader为null的问题

报错信息

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "F28DA_CW2.FlightsReader.getAirports()" because "this.flightReader" is null
    at F28DA_CW2.FlyingPlanner.leastCost(FlyingPlanner.java:206)
    at F28DA_CW2.FlyingPlannerMainPartBC.main(FlyingPlannerMainPartBC.java:29)

相关代码

主文件FlyingPlannerMainPartBC.java

import java.io.FileNotFoundException;

public class FlyingPlannerMainPartBC {

public static void main(String[] args) throws FlyingPlannerException, FileNotFoundException {

    FlyingPlanner fi;
    fi = new FlyingPlanner();
    try {
        fi.populate(new FlightsReader());

        // Implement here your user interface using the methods of Part B. You could
        // optionally expand it to use the methods of Part C.

    } catch (FileNotFoundException | FlyingPlannerException e) {
        e.printStackTrace();
    }

    FlightsReader flightReader = new FlightsReader();
    flightReader.getAirports();
    flightReader.getFlights();
    FlyingPlanner pr = new FlyingPlanner();
    System.out.println(pr.leastCost("EDI", "DXB")); // line: 29
    
}

}

FlyingPlanner类的leastCost方法

@Override
public Journey leastCost(String from, String to) throws FlyingPlannerException {
    // TODO Auto-generated method stub
    HashSet<String[]> airports = flightReader.getAirports(); //line206
    HashSet<String[]> flights = flightReader.getFlights();

    DefaultDirectedWeightedGraph<String, DefaultWeightedEdge> leastCost = new DefaultDirectedWeightedGraph<>(
            DefaultWeightedEdge.class);

    for (String[] flight : flights) {
        leastCost.addVertex(flight[1]);
        leastCost.addVertex(flight[3]);
        leastCost.addEdge(flight[1], flight[3]);
        leastCost.setEdgeWeight(flight[1], flight[3], Integer.parseInt(flight[5]));
    }

    DijkstraShortestPath<String, DefaultWeightedEdge> dijkstraAlg = new DijkstraShortestPath<>(leastCost);
    GraphPath<String, DefaultWeightedEdge> shortestPath = dijkstraAlg.getPath(from, to);

    int totalCost = 0;
    int totalHop = 0;
    int totalTime = 0;

    for (DefaultWeightedEdge defaultWeightedEdge : shortestPath.getEdgeList()) {
        totalCost = totalCost + (int) leastCost.getEdgeWeight(defaultWeightedEdge);
        totalHop = totalHop + 1;
        String v1 = leastCost.getEdgeSource(defaultWeightedEdge);
        String v2 = leastCost.getEdgeTarget(defaultWeightedEdge);
        System.out.println(totalHop + ". " + v1 + "--->" + v2);
    }

    Journey journey = new Journey();
    journey.setTotalCost(totalCost);
    journey.setTotalHop(totalHop);

    System.out.println(totalCost);
    System.out.println(totalHop);

    return journey;
}

FlightsReader类

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.Scanner;

public class FlightsReader {

private static final File flightsDatasetFolder = new File("FlightsDataset");
private static final File flightsDatasetFlights = new File(flightsDatasetFolder, "flights.csv");
private static final File flightsDatasetAirports = new File(flightsDatasetFolder, "airports.csv");

private HashSet<String[]> airports;
private HashSet<String[]> flights;

public FlightsReader() throws FileNotFoundException, FlyingPlannerException {
    this.airports = new HashSet<String[]>();
    this.flights = new HashSet<String[]>();

    // Adding flights, and building list of needed airport
    HashSet<String> airportsNeeded = new HashSet<String>();
    Scanner flightsScanner = new Scanner(flightsDatasetFlights);
    while (flightsScanner.hasNextLine()) {
        String line = flightsScanner.nextLine();
        String[] fields = line.split(",");
        String from = fields[1];
        String to = fields[3];
        airportsNeeded.add(from);
        airportsNeeded.add(to);
        this.flights.add(fields);
    }
    flightsScanner.close();

    // Adding airports
    Scanner airportsScanner = new Scanner(flightsDatasetAirports);
    while (airportsScanner.hasNextLine()) {
        String line = airportsScanner.nextLine();
        String[] fields = line.split(",");
        if (airportsNeeded.contains(fields[0])) {
            this.airports.add(fields);
        }
    }
    airportsScanner.close();
}

/**
 * Returns a hash set of airport details (0: airport code, 1: city, 2: airport
 * name)
 */
public HashSet<String[]> getAirports() {
    return this.airports;
}

/**
 * Returns a hash set of flight details (0: flight code, 1: airport code of
 * departure, 2: departure time GMT, 3: airport code of arrival, 4: arrival time
 * GMT, 5: flight cost)
 */
public HashSet<String[]> getFlights() {
    return this.flights;
}

}

问题根源

核心问题出在main方法的后半段:

  1. 新建的FlyingPlanner pr对象未调用populate方法,导致其内部的flightReader成员变量始终为null
  2. 前面已通过populate完成初始化的fi对象未被用来调用leastCost方法,属于无效创建
  3. 单独创建的flightReader对象仅调用了getAirports()和getFlights(),未关联到pr对象,无实际作用

调用pr.leastCost()时,pr内部的flightReader为null,触发空指针异常。

解决方案

修改main方法,选择以下两种方案之一即可:

方案一:复用已初始化的fi对象

import java.io.FileNotFoundException;

public class FlyingPlannerMainPartBC {

public static void main(String[] args) throws FlyingPlannerException, FileNotFoundException {

    FlyingPlanner fi = new FlyingPlanner();
    try {
        fi.populate(new FlightsReader());
        // 直接使用已初始化的对象调用方法
        System.out.println(fi.leastCost("EDI", "DXB"));
    } catch (FileNotFoundException | FlyingPlannerException e) {
        e.printStackTrace();
    }
}

}

方案二:给pr对象执行populate初始化

import java.io.FileNotFoundException;

public class FlyingPlannerMainPartBC {

public static void main(String[] args) throws FlyingPlannerException, FileNotFoundException {

    try {
        FlightsReader flightReader = new FlightsReader();
        FlyingPlanner pr = new FlyingPlanner();
        pr.populate(flightReader); // 关键:初始化内部的flightReader
        System.out.println(pr.leastCost("EDI", "DXB"));
    } catch (FileNotFoundException | FlyingPlannerException e) {
        e.printStackTrace();
    }
}

}

额外说明

  • FlyingPlanner的populate方法作用是将外部FlightsReader实例赋值给内部成员,必须在调用leastCost等依赖方法前执行
  • 清理代码中多余的未使用对象,避免逻辑混乱和资源浪费

内容的提问来源于stack exchange,提问作者lucas lootan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:07:11