简体   繁体   中英

Constructor gets Called TWice

I am trying to implement an ArrayList which saves details input by users and displays them. The code works Ok but the constructor gets called twice once from main and other from the StudentDetails Class. Is there a way to make it call just once ? Here is the Student Class having a main method calling object of StudentDetails class and the StudentDetails class which has an ArrayList.

public class Student2 {      

  public static void main(String[] args) {              
     StudentDetails sd1 = new StudentDetails();
     sd1.input();
     sd1.display();        
  }

  class StudentDetails {    
    int marks;
    String names;
    List<StudentDetails> sd = new ArrayList<>();

    public int getMarks() {
        return marks;
    }

    public void setMarks(int marks) {
        this.marks = marks;
    }

    public String getNames() {
        return names;
    }

    public void setNames(String names) {
        this.names = names;
    }

    public StudentDetails() {    
        System.out.println("Program Started");
    }

    public void input() {    
        int no;
        StudentDetails sDetails = new StudentDetails();
        System.out.println("How many students?");
        Scanner sc = new Scanner(System.in);
        no = sc.nextInt();

        for (int i = 0; i < no; i++) {
            System.out.println("Enter name of student" + (i + 1));
            sDetails.setNames(sc.next());
            System.out.println("Enter marks for same student");
            sDetails.setMarks(sc.nextInt());
            sd.add(sDetails);    
        }    
    }

    public void display() {
        for (int i = 0; i < sd.size(); i++) {                
            System.out.println("The name of student" + " " + (i + 1) + " " + "is" + " " + sd.get(i).getNames()
                    + " and marks are" + " " + sd.get(i).getMarks());    
        }
    }
}

You are calling it twice (to create two StudentDetails instances), and actually it's not enough. Your input() method should call it multiple times - once for each iteration of the loop - since you are adding these objects to a List and you don't want to add the same object multiple times.

You could avoid the creation of the object at the main by making input() and display() static methods and changing sd to a static variable.

public static void main(String[] args) {              
   StudentDetails.input();
   StudentDetails.display();        
}

...
static List<StudentDetails> sd = new ArrayList<>();
...
public static void input() {
    ...
    for (int i = 0; i < no; i++) {
        StudentDetails sDetails = new StudentDetails();
        System.out.println("Enter name of student" + (i + 1));
        sDetails.setNames(sc.next());
        System.out.println("Enter marks for same student");
        sDetails.setMarks(sc.nextInt());
        sd.add(sDetails);    
    } 
    ...
}

public static void display() {
    ...
}

Here is the updated class.

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

public class Student2 {

public static void main(String[] args) {

    StudentDetails sd1 = new StudentDetails();
    sd1.input();
    sd1.display();

}

class StudentDetails {

    int marks;
    String names;
    List<StudentDetails> sd = new ArrayList<>();

    public int getMarks() {
        return marks;
    }

    public void setMarks(int marks) {
        this.marks = marks;
    }

    public String getNames() {
        return names;
    }

    public void setNames(String names) {
        this.names = names;
    }

    public StudentDetails() {

        System.out.println("Program Started");
    }

    public void input() {

        int no;         
        System.out.println("How many students?");
        Scanner sc = new Scanner(System.in);
        no = sc.nextInt();

        for (int i = 0; i < no; i++) {
            System.out.println("Enter name of student" + (i + 1));
            setNames(sc.next());
            System.out.println("Enter marks for same student");
            setMarks(sc.nextInt());
            sd.add(this);

        }
        sc.close();
    }

    public void display() {
        for (int i = 0; i < sd.size(); i++) {

            System.out.println("The name of student" + " " + (i + 1) + " "
                    + "is" + " " + sd.get(i).getNames() + " and marks are"
                    + " " + sd.get(i).getMarks());

        }
    }
}
}

As an option to @Eran´s answer you might want to go with a more proper Class Design. At the moment the List<StudentDetails> is depending on an instance of StudentDetails , which in my eyes doesn´t make sense to begin with.

Create an additional Class that acts as a Manager for the StudenDetails

public class Student2 {

    public static void main(String[] args) {
        // We create a Dictionary here now. This holds the StudentDetails now
        StudenDictionary sd1 = new StudenDictionary();
        sd1.input();
        sd1.display();
    }

    static class StudenDictionary {
        List<StudentDetails> sd = new ArrayList<>();

        static Scanner sc = new Scanner(System.in);

        public void input() {
            int no;

            System.out.println("How many students?");
            no = sc.nextInt();

            for (int i = 0; i < no; i++) {
                System.out.println("Enter name of student" + (i + 1));
                // Store in variables and use a proper constructor
                String names = sc.next();
                System.out.println("Enter marks for same student");
                int marks = sc.nextInt();
                // StudenDetails variable in loop now, caring for scope now
                StudentDetails sDetails = new StudentDetails(names, marks);
                sd.add(sDetails);
            }
        }

        public void display() {
            for (int i = 0; i < sd.size(); i++) {
                System.out.println("The name of student" + " " + (i + 1) + " " + "is" + " " + sd.get(i).getNames()
                        + " and marks are" + " " + sd.get(i).getMarks());
            }
        }
    }

    static class StudentDetails {
        int marks;
        String names;

        public int getMarks() {
            return marks;
        }

        public void setMarks(int marks) {
            this.marks = marks;
        }

        public String getNames() {
            return names;
        }

        public void setNames(String names) {
            this.names = names;
        }

        // Use a proper constructor
        public StudentDetails(String names, int marks) {
            this.names = names;
            this.marks = marks;
        }

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM