对象的变量假定错误的值 - 在创建时,一切都很好

时间:2016-03-09 10:34:00

标签: java

我一直在努力解决这个问题,但到目前为止我无法解决这个问题,所以我希望你能帮助我。在此先感谢您的帮助。

快速解释: - 我把问题存在于" file.txt"从课堂问题到一个对象。 - 在创建对象的那一刻,一切都应该如此。在我完成创建对象的过程中,答案是正确的。

问题: - 当我稍后尝试获得问题的答案,即变量String []选项时,首先迭代他们打印正确答案,然后两个问题都获得相同的选项答案。

我在这里做错了什么?

主要类

//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();
    }

    }

问题类

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;
    }
 }

控制台结果:

2 个答案:

答案 0 :(得分:1)

问题是,您每次都在处理options数组的相同引用。这是一个问题,证明了什么是错的,以及如何解决它。

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);
        }


    }
}

输出:

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]

正如您所看到的,由于您不在此基本示例中重新分配选项,因此您也会影响之前创建的每个Question,因为它们共享answers数组的相同引用值。

要修复它,请在每次迭代开始时重新分配数组:

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);
        }


    }
}

输出:

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]

正如您所看到的,您将能够获得所需的输出,每个Question有四种不同的答案。

答案 1 :(得分:1)

我认为问题在于你处理变量的方式。在您的代码中,您有一个名为options的字符串数组。这个数组在内存中占有一席之地,让我们称之为M1。

创建对象时,将“选项”数组作为参数传递给对象问题。问题会为选项创建一个字段。现在您的主类中有options数组,而您的问题中有options数组这里的问题是你有多少个原始数组副本?答案是1个副本。方法fillQuizQuestions中的变量“options”和你创建的Questions对象中的“options”字段都指向相同的数组。他们指向位置M1。换句话说,它们指向物理内存中的相同位置。

因此,当您更改一个变量时,另一个变量也会发生变化。你需要做的是在循环的每次迭代中创建一个新的“选项”数组。换句话说,在fillQuizQuestions方法中,代码应该改为:

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

总之,在Java中,当涉及对象(即除了基本类型int,double,float,boolean,char等之外的所有内容)时,对于两个对象a和b,你做a=b你没有相同对象的两个副本,但有一个副本和两个指针指向它。这里的一个例外是包装基本类型的对象(即Integer,Double,Char等)。赋值(=)在此创建对象的新副本。

下面是一个小示例:

 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]);

}