1

コードを実行するには、コードをコピーしてIDEに貼り付けるだけです。すべてがそこにあります。これは、Observer-Observableデザインパターンを使用する飛行監視プログラムです。FlightStautsMonitorは、フライトのフライトステータス(整数)を監視するオブザーバーです。FlightStatusChangeEventは、フライトのステータスの変更を記録するクラスです。デモはドライバークラス、またはメインのクラスです。

私の問題は、Observer andObservableAPIを使用しているかどうかわからないことです。ランタイムエラーのある出力が表示されます-

Old flight status
F:1, S: 0
F:2, S: 0
F:3, S: 0
F:4, S: 0
F:5, S: 0
Exception in thread "main" java.lang.StackOverflowError
at java.util.Vector.toArray(Unknown Source)
at java.util.Observable.notifyObservers(Unknown Source)
at demo.Flight.updateStatus(Demo.java:40)
at demo.FlightStatusMonitor.update(Demo.java:91)
at java.util.Observable.notifyObservers(Unknown Source)

問題の理由は何ですか?このコードを修正するにはどうすればよいですか?

//package demo;

import java.util.*;

class FlightStatusChangeEvent{

int status;
Flight flight;

FlightStatusChangeEvent(int statusCode, Flight flight){

    this.status = statusCode;
    this.flight = flight;

}

public int getStatus(){return this.status;}

public Flight getFlight(){return this.flight;}


}

class Flight extends Observable{

int status;// 0 = on time, -1 = late, +1 = before scheduled time
String flightCode;

Flight(String flightCode){

    this.flightCode = flightCode;

}

public void updateStatus(int statusCode){

    this.status = statusCode;
    FlightStatusChangeEvent fsce = new FlightStatusChangeEvent(status, this);
    setChanged();
    notifyObservers(fsce);

}


public String getFlightCode(){return this.flightCode;}

public String toString(){return "F:" + flightCode + ", S: " + status;}

}


 class FlightStatusMonitor implements Observer{

public static ArrayList<Flight> flights = new ArrayList<Flight>();

static{

    for(int i = 1; i < 6; i++){

        Flight ff = new Flight("" + i);
        flights.add(ff);        
    }

}

//keep calling this method every 10 sec to get latest flight status
public static void displayStatusOfFlights(){

    //print all flight statuses in array list - flights
    for(Flight fl : flights){
        System.out.println(fl);

    }

}

public void update(Observable flight, Object flightStatusEvent){

    FlightStatusChangeEvent fsce = (FlightStatusChangeEvent) flightStatusEvent;     
    Flight fl = fsce.getFlight();
    String code = fl.getFlightCode();
    int status = fsce.getStatus();

    //find the flight in array flights and then update its status
    for(int i = 0; i < flights.size(); i++){

        Flight fli = flights.get(i);
        String flCode = fli.getFlightCode();

        if(flCode.equals(code)){
            fli.updateStatus(status);
            System.out.print("Flight status updated !");

            break;

        }

    }


}

}


 public class Demo{

public static void main(String[]args){

    FlightStatusMonitor fsm = new FlightStatusMonitor();
    System.out.println("Old flight status");
    ArrayList<Flight> fllist = fsm.flights;
    fsm.displayStatusOfFlights();

    for(Flight fl : fllist ){

        fl.addObserver(fsm);

    }

    fsm.flights.get(1).updateStatus(-1);
    System.out.println("New flight status");        
    fsm.displayStatusOfFlights();

}


}
4

2 に答える 2

3

Flight.updateStatus呼んでいるnotifyObersevers

FlightStatusMonitor#updateflights.get(x).updateStatus...start endless を呼び出しています。

上記のオブジェクトから受信したイベント通知内のオブジェクトの状態を更新しないでください...

スタック トレースのクリティカル セクションは次のとおりです。

Exception in thread "main" java.lang.StackOverflowError
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.Vector.toArray(Vector.java:687)
    at java.util.Observable.notifyObservers(Observable.java:154)
    at teststackoverflow.Demo$Flight.updateStatus(Demo.java:73)
    at teststackoverflow.Demo$FlightStatusMonitor.update(Demo.java:125)
    at java.util.Observable.notifyObservers(Observable.java:159)
    at teststackoverflow.Demo$Flight.updateStatus(Demo.java:73)
    at teststackoverflow.Demo$FlightStatusMonitor.update(Demo.java:125)

できます(一番下から)、FlightStatusMonitor.update呼び出しFlight#updateStatusています、呼び出しObservable.notifyObserversています、呼び出していますFlightStatusMonitor.update

また、デバッグ フラグを true に設定してコードをコンパイルすることをお勧めします ( javac -g)

可能な修正で更新

なので、フライトコードを比較するだけでなく、各フライトのフライト状況を比較して、状況が一致しないものだけを変更する必要があると思います。

public void update(Observable flight, Object flightStatusEvent) {

    FlightStatusChangeEvent fsce = (FlightStatusChangeEvent) flightStatusEvent;
    Flight fl = fsce.getFlight();
    String code = fl.getFlightCode();
    int status = fsce.getStatus();

    //find the flight in array flights and then update its status
    for (int i = 0; i < flights.size(); i++) {

        Flight fli = flights.get(i);
        String flCode = fli.getFlightCode();

        if (flCode.equals(code)) {
            //** Possible Fix **//
            if (fli.status != fl.status) {
                fli.updateStatus(status);
                System.out.print("Flight status updated !");
            }
        }
    }
}
于 2013-03-24T04:44:56.450 に答える
3

アプリケーションの再帰が深すぎるためにスタック オーバーフローが発生すると、StackOverflowErrorがスローされます。

あなたの問題はupdate方法にあります。updateStatusメソッドを呼び出すと、updateStatusメソッドが再度呼び出されますupdate。削除fli.updateStatus(status);すると問題が解決します。

public void update(Observable flight, Object flightStatusEvent) {

        FlightStatusChangeEvent fsce = (FlightStatusChangeEvent) flightStatusEvent;
        Flight fl = fsce.getFlight();
        String code = fl.getFlightCode();
        int status = fsce.getStatus();

        // find the flight in array flights and then update its status
        for (int i = 0; i < flights.size(); i++) {

            Flight fli = flights.get(i);
            String flCode = fli.getFlightCode();

            if (flCode.equals(code)) {
                // THIS WILL CAUSE STACKOVERFLOWERROR
                fli.updateStatus(status);
                System.out.print("Flight status updated !");

                break;

            }

        }

    }
于 2013-03-24T04:47:47.953 に答える