0

I have written a code in which I have made an interface and a class that implements that interface. Now when I run the code, i give my self 2 options i.e. 1 to Enter string and 2 to quit. Now when i run the code, if i select 1, it lets me put in string, but after this when i press 0, it gives me error: Exception in thread "main" java.lang. Can some body please help me figure out what I am missing here. Below is the code:

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

public interface ITimsSaveable {

    List<String> write();  // this will save the data;
    void read (List<String> savedValues);  //this will print the data

}


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

public class TimsPlayers implements ITimsSaveable {
    private String name;
    private int hitPoints;
    private int strength;
    private String weapon;

    public TimsPlayers(String name, int hitPoints, int strength) {
        this.name = name;
        this.hitPoints = hitPoints;
        this.strength = strength;
        this.weapon = "Sword";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHitPoints() {
        return hitPoints;
    }

    public void setHitPoints(int hitPoints) {
        this.hitPoints = hitPoints;
    }

    public int getStrength() {
        return strength;
    }

    public void setStrength(int strength) {
        this.strength = strength;
    }

    public String getWeapon() {
        return weapon;
    }

    public void setWeapon(String weapon) {
        this.weapon = weapon;
    }
    //now go to generate > to string method

    @Override
    public String toString() {
        return "TimsPlayers{" +
                "name='" + name + '\'' +
                ", hitPoints=" + hitPoints +
                ", strength=" + strength +
                ", weapon='" + weapon + '\'' +
                '}';
    }
    //now let us create stubs, i.e. the empty methods from interface

    @Override
    public List<String> write() {
        List<String > values = new ArrayList<String >();
        values.add(0,this.name);
        values.add(1,""+this.hitPoints); //"" is quick trick to convert int to String
        values.add(2,""+this.strength);
        values.add(3,this.weapon);
        return values;
    }

    @Override
    public void read(List<String> savedValues) {
        if ((savedValues != null) && (savedValues.size() > 0)) {
           this.name = savedValues.get(0);
           this.hitPoints = Integer.parseInt(savedValues.get(1));
           this.strength = Integer.parseInt(savedValues.get(2));
           this.weapon = savedValues.get(3);
        }
        // now let us go back to our main class
    }
}


public class Main {

    public static void main(String[] args) {

    TimsPlayers tim = new TimsPlayers("Tim",10,15);
        System.out.println(tim.toString());
        saveObject(tim);

        tim.setHitPoints(8);
        System.out.println(tim);
        tim.setWeapon("Stormbringer");
        saveObject(tim);
        loadObject(tim);
        System.out.println(tim);

    }
    public static ArrayList<String> readValues() {
        ArrayList<String> values = new ArrayList<String>();

        Scanner scanner = new Scanner(System.in);
        boolean quit = false;
        int index = 0;
        System.out.println("Choose\n" +
                "1 to enter a string\n" +
                "0 to quit");

        while (!quit) {
            System.out.print("Choose an option: ");
            int choice = scanner.nextInt();
            scanner.nextLine();
            switch (choice) {
                case 0:
                    quit = true;
                    break;
                case 1:
                    System.out.print("Enter a string: ");
                    String stringInput = scanner.nextLine();
                    values.add(index, stringInput);
                    index++;
                    break;
            }
        }
        return values;
    }

    public static void saveObject(ITimsSaveable objectToSave) { //ITims is the interface that is being implemented by the player
    

//class,so we can use ITims as object type
    for (int i = 0; i < objectToSave.write().size(); i++) {
        System.out.println("Saving " + objectToSave.write().get(i) + " to storage device");
    }
    }
        public static void loadObject (ITimsSaveable objectToLoad) {
            ArrayList<String > values = readValues();
            objectToLoad.read(values);
    
    }
    }

Stacktrace:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1 at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64) at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70) at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248) at java.base/java.util.Objects.checkIndex(Objects.java:373) at java.base/java.util.ArrayList.get(ArrayList.java:427) at org.mm.sandbox.so.TimsPlayers.read(TimsPlayers.java:77) at org.mm.sandbox.so.Main.loadObject(Main.java:62) at org.mm.sandbox.so.Main.main(Main.java:17)

Dropout
  • 13,653
  • 10
  • 56
  • 109
  • Can you share the exception with the full stack trace? –  Nov 27 '20 at 13:19
  • @tibetiroka I've added the stacktrace that OP left out.. `TimsPlayers.java:77` indexOutOfBounds – Dropout Nov 27 '20 at 13:27
  • @Dropout Be careful about adding stack traces yourself. Far too often, people put up code here that isnt exactly what they are having trouble with. So even when you got the above from running the provided code ... as said: be careful about assuming that the exception YOU get is the same the OP is worrying about. – GhostCat Nov 27 '20 at 13:41
  • And in case the exception is the right one ... see https://stackoverflow.com/questions/5554734/what-causes-a-java-lang-arrayindexoutofboundsexception-and-how-do-i-prevent-it – GhostCat Nov 27 '20 at 13:42
  • @GhostCat noted, thanks.. – Dropout Nov 27 '20 at 13:48

1 Answers1

0

This method

@Override
public void read(List<String> savedValues) {
    if ((savedValues != null) && (savedValues.size() > 0)) {
        this.name = savedValues.get(0);
        this.hitPoints = Integer.parseInt(savedValues.get(1));
        this.strength = Integer.parseInt(savedValues.get(2));
        this.weapon = savedValues.get(3);
    }
    // now let us go back to our main class
}

expects the savedValues to be completely filled, i.e. having 4 elements - name, HP, strength and weapon. You do savedValues.size() > 0 but that doesn't mean you didn't just input one of the required and then stopped and it still tries to access an element which does not exist - this.hitPoints = Integer.parseInt(savedValues.get(1));

Dropout
  • 13,653
  • 10
  • 56
  • 109
  • Thanks, gotcha. Also, any pointers on how should i go about catching such breaks? – Bilal Ahmed Khan Nov 27 '20 at 13:43
  • @BilalAhmedKhan I'd switch to a more robust data structure. For example you could be filling out a `HashMap` to keep the settings. You then don't have to rely on the List being filled in a certain order and what not. You'd just use `values.get("hitPoints")` to retrieve it from the Map. You'd have to change the scanner part so it asks for both what is being stored and then the value. Or instead of just handling `1` make it so `1` stores name, `2` stores HP and so on. For example. – Dropout Nov 27 '20 at 13:46
  • @BilalAhmedKhan No problem. If you could designate it as an answer that would be cool. – Dropout Nov 27 '20 at 14:04
  • Thanks sir, acknowledged and designated. – Bilal Ahmed Khan Nov 28 '20 at 18:56