Variable of an object assumes wrong values - At the moment of creation everything is ok

I have been trying hard to solve this on my way but till now i was not able to, so i hope you can help me. Thanks in advance for the help.

Quick explanation: - I put the questions that exist in a "file.txt" into an object from class Question. - At the moment of the creation of the objects, everything is as it should. The moment i finish the process of creating the objects, the answers are correct.

The problem: - When later i try to obtain the answers of the question i.e, the variable String [] options, first iteration they print the correct answers, then both questions obtain the same options answers.

What i'm doing wrong here?

Main Class

//Method that first prints the answer well, then with wrong values
    private void printingTest(){
        AllQuestions.get(0).printOptions();
        AllQuestions.get(1).printOptions();
    }


private void fillQuizQuestions(){
        int QuestionID = 0;
        String question = null;
        String [] options = new String[4];
        String solution = null;
        try{
             Scanner input = new Scanner(System.in);
             File file = new File("questions");
             input = new Scanner(file);
             while (input.hasNextLine()) {
                    String line = input.nextLine();
                    if (line.equals("Question:")){
                        question = input.nextLine();

                        for(int i=0; i<4; i++){
                            options[i] = input.nextLine();             
                        }
                      solution = input.nextLine();
                        QuestionID++;
                        Question newQuestion = new Question(QuestionID, question, options, solution);
                        AllQuestions.add(newQuestion);


                    }
                }

                input.close();


        }
       catch (Exception ex) {
        ex.printStackTrace();
    }

    }

Question Class

public class Question {
    int questionID;
    String question = null;
    String[] options = new String[4];
    String solution = null;
    boolean QuestionUsed = false;

    public Question(int questionID, String question, String[] options, String solution){
        this.questionID = questionID;
        this.question = question;
        this.options = options;
        this.solution = solution;
        printOptions();

    }

    public void printOptions(){
        System.out.println("Basic Test: "+question);
        System.out.println(options[0]);
        System.out.println(options[1]);
        System.out.println(options[2]);
        System.out.println(options[3]);
    }




    public int getQuestionID() {
        return questionID;
    }

    public String getQuestion(){
        return question;
    }

    public boolean QuestionUsed(){
        return QuestionUsed;
    }


    public String[] getOptions() {
        return options;
    }


    public void setOptions(String[] options) {
        this.options = options;
    }


    public String getSolution() {
        return solution;
    }

    public void setQuestionUsed(){
        QuestionUsed = true;
    }
 }

Console result:

Upvotes: 0

Views: 56

Answers (2)

orestis
orestis

Reputation: 972

I think the problem is in the way you handle the variables. In your code you have an array of Strings that is called options. This array holds a place in memory, let's call that place M1.

When you create an object, you pass the "options'' array as a parameter to the object Questions. Questions creates a field for the options. Now you have the options array in your main class and the options array in your Questions object. The issue here is how many copies of the original array do you have? The answer is 1 copy. Both the variable "options" in method fillQuizQuestions and the field "options'' in the Questions object that you have created point to the same array. They point at the location M1. In other words, they point to the same location in your physical memory.

As a result, when you change one variable the other one is going to change as well. What you need to do is to create a new "options'' array in every iteration of the loop. In other words, in the fillQuizQuestions method, the code should be changed to the following:

   options=new String[4];
   for(int i=0; i<4;i++) 
        options[i] = input.nextLine();             

In summary, in Java, when it comes to Objects (i.e. everything except for the basic types int,double,float,boolean,char,etc) when for two Objects a and b, you do a=byou do not have two copies of the same Object but one copy and two pointers pointing at it. One exception here are the objects that wrap the basic types (i.e. Integer, Double, Char,etc.). Here the assignment (=) creates a new copy of the object.

A little demonstration example follows:

 public static void main(String args[])
{
    Integer x=5;
    Integer y;
    y=x;
    System.out.println(x+" "+y);
    y=10;
    System.out.println(x+" "+y);
    Integer[] a={5}; //array of one item
    Integer[] b=a;
    System.out.println(a[0]+" "+b[0]);
    b[0]=10;
    System.out.println(a[0]+" "+b[0]);

}                          

Upvotes: 1

SomeJavaGuy
SomeJavaGuy

Reputation: 7347

Here´s the problem, you are working on the same reference of the options array every time. Here´s a problem demonstrating what is wrong, and how you could fix it.

public class Question {
    String question;
    String[] answers = new String[4];

    public Question(String question, String[] answers){
        this.question = question;
        this.answers = answers;
    }

    @Override
    public String toString() {
        return question+"\n" + Arrays.toString(answers);
    }

    public static void main(String[] args) {
        String[] options = new String[4];
        int counter = 0;

        List<Question> list = new ArrayList<Question>();

        for (int i = 0;i<10;++i) {
            for(int j = 0;j<4;++j,++counter) {
                options[j] = counter+"";
            }
            Question q = new Question(counter+"",options);
            list.add(q);
        }

        for(Question q : list) {
            System.out.println(q);
        }


    }
}

output:

4
[36, 37, 38, 39]
8
[36, 37, 38, 39]
12
[36, 37, 38, 39]
16
[36, 37, 38, 39]
20
[36, 37, 38, 39]
24
[36, 37, 38, 39]
28
[36, 37, 38, 39]
32
[36, 37, 38, 39]
36
[36, 37, 38, 39]
40
[36, 37, 38, 39]

As you can see, since you don´t reassign options in this basic example you are also influencing each previously created Question, since they all share the same value of reference for the answers array.

To fix it reassign the array at the start of each iteration:

public class Question {
    String question;
    String[] answers = new String[4];

    public Question(String question, String[] answers){
        this.question = question;
        this.answers = answers;
    }

    @Override
    public String toString() {
        return question+"\n" + Arrays.toString(answers);
    }

    public static void main(String[] args) {
        String[] options = new String[4];
        int counter = 0;

        List<Question> list = new ArrayList<Question>();

        for (int i = 0;i<10;++i) {
            options = new String[4]; // Reassign the array to create another value of reference.
            for(int j = 0;j<4;++j,++counter) {
                options[j] = counter+"";
            }
            Question q = new Question(counter+"",options);
            list.add(q);
        }

        for(Question q : list) {
            System.out.println(q);
        }


    }
}

output:

4
[0, 1, 2, 3]
8
[4, 5, 6, 7]
12
[8, 9, 10, 11]
16
[12, 13, 14, 15]
20
[16, 17, 18, 19]
24
[20, 21, 22, 23]
28
[24, 25, 26, 27]
32
[28, 29, 30, 31]
36
[32, 33, 34, 35]
40
[36, 37, 38, 39]

As you can see you would be able to get the desired output, each Question has four different answers.

Upvotes: 1

Related Questions