【问题标题】:List of 'unique' objects in JavaJava中的“唯一”对象列表
【发布时间】:2019-02-09 16:24:22
【问题描述】:

我正在和我的同学一起做学校作业。我们正在制作一个出租车应用程序,您可以在其中启动和停止出租车,询问当前价格并在出租车停止时获得总价格。目前它工作正常。但是如果我们启动出租车 1,然后启动出租车 2,就会出现问题。出租车 1 的开始和结束时间被新对象(出租车 2)的开始和结束时间覆盖——即使我们从和 arraylist 基于我在系统中输入的用户数。

Main.java 中的代码:

import java.text.DecimalFormat;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Taxi taxi = new Taxi();
        System.out.println("Hej og velkommen til Damn Fast Taxis.");
        boolean isEnd = false;
        DecimalFormat decimalFormat = new DecimalFormat("#.0");
        while(!isEnd) {

            Taxi chosenTaxi;

            System.out.println("1. Start en taxi.");
            System.out.println("2. Stop en taxi.");
            System.out.println("3. Pause en taxi.");
            System.out.println("4. Spørg efter pris.");
            System.out.println("5. Gratis tur.");
            System.out.println("6. Tilføj antal taxier.");

            Scanner sc = new Scanner(System.in);
            String choice = sc.nextLine();

            switch (choice) {
                case "1":
                    if (taxi.getTaxiListPrint().size()>=1) {

                        Scanner startTaxiNumber = new Scanner(System.in);
                        int numberChoice = startTaxiNumber.nextInt();
                        chosenTaxi = taxi.chooseTaxi(numberChoice);

                        chosenTaxi.setStartTime();
                        break;
                    } else {
                        System.out.println("Ingen taxier er oprettet i systemet.");
                        break;
                    }

                case "2":

                    if (taxi.getTaxiListPrint().size()>=1) {
                        Scanner endTaxiNumber = new Scanner(System.in);
                        int numberChoice = endTaxiNumber.nextInt();
                        chosenTaxi = taxi.chooseTaxi(numberChoice);

                        chosenTaxi.setEndTime();

                        if (!chosenTaxi.isStopped()) {
                            System.out.println("Turen varede " + decimalFormat.format(((chosenTaxi.getEndTime() - chosenTaxi.getStartTime()) / 100)*0.1) + " sekunder.");
                            Price price = new Price();
                            String finalPrice = price.calculatePrice(chosenTaxi.getStartTime(), chosenTaxi.getEndTime(), decimalFormat);
                            System.out.println("Pris: " + finalPrice + " dollars.");
                            chosenTaxi.setStopped(true);
                        } else {
                            System.out.println("Denne taxi er allerede blevet stoppet.");
                        }
                        break;
                    } else {
                        System.out.println("Ingen taxier er oprettet i systemet.");
                    }
                case "3":
                    break;
                case "4":

                    if (taxi.getTaxiList().size()>=1) {
                        Scanner currentPriceTaxiNumber = new Scanner(System.in);
                        int numberChoice = currentPriceTaxiNumber.nextInt();
                        Taxi currentChosenTaxi = taxi.chooseTaxi(numberChoice);

                        currentChosenTaxi.setEndTime();
                        if (!currentChosenTaxi.isStopped()) {
                            Price priceNow = new Price();
                            String currentPrice = priceNow.calculatePrice(currentChosenTaxi.getStartTime(), currentChosenTaxi.getEndTime(), decimalFormat);
                            System.out.println("Pris: " + currentPrice + " dollars.");
                        } else {
                            System.out.println("Denne taxi er allerede blevet stoppet.");
                        }
                        break;
                    } else {
                        System.out.println("Ingen taxier er oprettet i systemet.");
                        break;
                    }

                case "5":

                    break;
                case "6":
                    System.out.println("Hvor mange taxier vil du tilføje?");
                    Scanner taxaNumber = new Scanner(System.in);
                    int number = taxaNumber.nextInt();
                    for (int i = 0; i<number;i++) {
                        taxi.addTaxi(taxi);
                    }
                    System.out.println(number + " " + "Taxa'er tilføjet!");
                    break;
                default:
                    isEnd = true;

     break;

出租车类:

import java.util.ArrayList;
import java.util.List;

public class Taxi {

    private long startTime;
    private long endTime;
    private boolean isStopped = false;
    private List<Taxi> taxiList = new ArrayList<>();

    public void addTaxi(Taxi taxi) {
        taxiList.add(taxi);
    }

    public Taxi chooseTaxi(int choice) {
        return taxiList.get(choice - 1);
    }

    public List<Taxi> getTaxiListPrint() {

        for(int i = 1; i<taxiList.size() + 1;i++) {
            System.out.println("Taxi: " + i);
        }
        return taxiList;
    }

    public List<Taxi> getTaxiList() {
        return taxiList;
    }

    public long getStartTime() {
        return startTime;
    }

    public long getEndTime() {
        return endTime;
    }

    public boolean isStopped() {
        return isStopped;
    }

    public void setStartTime() {
        this.startTime = System.currentTimeMillis();
    }

    public void setEndTime() {
        this.endTime = System.currentTimeMillis();
    }

    public void setStopped(boolean stopped) {
        isStopped = stopped;
    }
}

如果我的代码很乱,我很抱歉,我对这门语言很陌生。简短的问题是:如何定义不同的对象,以便程序不会在每次创建新的出租车实例时都覆盖?

非常感谢。 /尼克

【问题讨论】:

  • 请注意,我们通常会要求您尝试构建产生问题的尽可能短的代码,从而消除与展示问题无关的所有功能。请参阅帮助中心中的minimal reproducible example 定义,以及sscce.org 上的“修剪技巧”部分
  • 也就是说——一般来说,让你的TaxiList 成为你的class Taxi 的一部分是个坏主意。每个Taxi 实例应该只代表一辆出租车。
  • 每辆出租车都有自己的出租车列表。这是为什么呢?
  • 另外,您的 for (int i = 0; i&lt;number;i++) { taxi.addTaxi(taxi); } 循环一遍又一遍地添加 same 出租车,因此您的列表中只有一堆对完全相同的出租车的引用,所以不管用户输入的号码是同一辆出租车。如果您希望它们成为不同的出租车,则需要类似于for (int i = 0; i&lt;number;i++) { taxiList.addTaxi(new Taxi()); }(假设您构建了taxiList)。

标签: java object unique


【解决方案1】:

我认为最简单的更改是将 Taxi 类中的这些方法更改为静态:

private static List<Taxi> taxiList = new ArrayList<>();

public static void addTaxi(Taxi taxi) {
    taxiList.add(taxi);
}

public static Taxi chooseTaxi(int choice) {
    return taxiList.get(choice - 1);
}

public static List<Taxi> getTaxiListPrint() {

    for (int i = 1; i < taxiList.size() + 1; i++) {
        System.out.println("Taxi: " + i);
    }
    return taxiList;
}

public static List<Taxi> getTaxiList() {
    return taxiList;
}

将这些方法改为静态形式,例如:

Taxi currentChosenTaxi = taxi.chooseTaxi(numberChoice);

改成

Taxi currentChosenTaxi = Taxi.chooseTaxi(numberChoice);

然后给经理添加不同的出租车:

            case "6":
                System.out.println("Hvor mange taxier vil du tilføje?");
                Scanner taxaNumber = new Scanner(System.in);
                int number = taxaNumber.nextInt();
                for (int i = 0; i < number; i++) {
                    Taxi.addTaxi(new Taxi());
                }
                System.out.println(number + " " + "Taxa'er tilføjet!");
                break;

注意:你不需要每次都 make new Scanner(System.in),如果你放在循环之外,你可以使用一个。

【讨论】:

    【解决方案2】:

    仅包含在您的类中构成 Taxi 的属性

    正如 cmets 所说,在您的 Taxi 类中使用 taxiList 并不是一个好主意。您的Taxi 类应该只具有构成Taxi必要属性。更好的结构应该是这样的

    public class Taxi {
        private long startTime;
        private long endTime;
        private boolean isStopped = false;
    
        // Add the necessary getters & setters for the above attributes here
    }
    

    通过ListTaxiManager 类管理您的出租车

    要保留您的 taxiList,您有 2 个选项

    1. Main 类中,定义一个List&lt;Taxi&gt; taxiList = new ArrayList&lt;&gt;()
    2. 创建一个单独的类来保存 list 和控制其项目的逻辑。例如TaxiManager

    第一个选项是在出租车上进行少量可能操作的好方法。如果您想从Main 类中抽象出出租车管理逻辑,2nd 选项会更好。它可以是这样的

    public class TaxiManager {
        private List<Taxi> taxiList;
        public class TaxiManager() { taxiList = new ArrayList<>(); }
    
        // Here are some "management" methods you can use
        // DON'T FORGET TO HANDLE EXCEPTIONS (for example ArrayOutOfBounds, ...)
    
        public void addTaxi(Taxi newTaxi) { taxiList.add(newTaxi); }
        public Taxi getTaxiAtIndex(int index) { return taxiList.get(index); }
        public void stopTaxiAtIndex(int index) { taxiList.get(index).stop(); }
    
        // Add the necessary operations here
    }
    

    如何在 Main 类中使用它

    创建一个新的TaxiManager 并根据您选择的逻辑调用您的方法(switch case

    public class Main {
        public static void main(String[] args) {
            TaxiManager taxiManager = new TaxiManager();
    
            Scanner sc = new Scanner(System.in);
            String choice = sc.nextLine();
    
            switch (choice) {
                case "add": {
                    taxiManager.addTaxi(new Taxi());
                    break;
                }
                // Include other options
            }
        }
    }
    

    回答“唯一对象”的问题 => 使用Singleton

    确保一个类只有一个实例,并提供一个全局访问点

    如果您想从不同的“类”调用TaxiManager 并仍然保留该经理唯一性,这可能是您的TaxiManager 的不错选择。然后,您可以放心,您的 出租车 不会重复。 如果你想走这条路,你的TaxiManager 看起来像这样

    public class TaxiManager {
        private List<Taxi> taxiList;
        private TaxiManager() {}
    
        private static class SingletonHolder {
            private static final TaxiManager INSTANCE = new TaxiManager();
        }
    
        public static TaxiManager getInstance() {
            return SingletonHolder.INSTANCE;
        }
    
        // Add other methods here
    }
    

    要从您的 Main 类中调用它,请使用它

    TaxiManager taxiManager = TaxiManager.getInstance();
    

    【讨论】:

      猜你喜欢
      • 2012-07-11
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 2015-04-06
      相关资源
      最近更新 更多