Search code examples
javaclassarraylistcompiler-errorsbufferedreader

How do I call a list from other classes?


Okay so I am building a program that will sort grades and records of students. It is a command-line program and when run it will start by asking for user input. there are several commands such as exit(exits program), load [file name](loads a file name), student [student name] (loads student records), etc. the others are not important. Well basically what I am wondering and what I am stuck on is all those functions will be in separate classes and will be called when the user inputs a specific command, but if I put the "load" command in its own class, then how do I get it to share its information with the other classes? I know I have to use BufferReader to read in the files, but how would I go implementing my load class, or if there is a better way feel free to say so. here is my code so far. there isn't much on my other classes because I feel like I need to figure out how to read in and share the file with the other classes first.

import java.util.*;
import java.io.*;
public class program7
{
    public static void main(String[] args)
    {
        Scanner scan = new Scanner(System.in);
        System.out.println("Grade Stats by ");
        System.out.print(">");
        while(scan.hasNextLine())
        {

            String input = scan.nextLine();

            if(input.equals("exit"))
            {
                System.exit(0);
            }
            else if(input.equals("help"))
            {
                System.out.println("exit                   - program closes.");
                System.out.println("load [filename]        - loads a class database specified in [filename].");
                System.out.println("students               - prints out a list of students from the class, along ");
                System.out.println("                         with total points, and final grades for each student.");
                System.out.println("assignments            - prints out a list of assignments from the file, along with points possible");
                System.out.println("student [student name] - Prints report for the student");
                System.out.print(">");
            }
            else if(input.contains("load"))
            {
                String[] split = input.split(" ");
                LoadStudents loadStudents = new LoadStudents(split[1]);
                loadStudents.getFromFile();
                System.out.print(">");
            }
            else if(input.equals("students"))
            {
                Students students = new Students();
                students.printer();

                System.out.print(">");
            }
            else if(input.equals("assignments"))
            {

                System.out.print(">");
            }
            else if(input.contains("student"))
            {
                String[] split = input.split(" ");
                Student student = new Student(split[1]);
                System.out.print(">");
            }
            else if(input.contains("assignment"))
            {

            }
            else if(input.equals("grades"))
            {

            }
            else
            {
                System.out.println("exit                   - program closes.");
                System.out.println("load [filename]        - loads a class database specified in [filename].");
                System.out.println("students               - prints out a list of students from the class, along ");
                System.out.println("                         with total points, and final grades for each student.");
                System.out.println("assignments            - prints out a list of assignments from the file, along with points possible");
                System.out.println("student [student name] - Prints report for the student");
                System.out.print(">");
            }
        }
    }

}

That is my main class, but here is my Load and Students class.

import java.util.*;
import java.io.*;
public class LoadStudents
{
    public String inputFile;
    public List<Object> info = new ArrayList<Object>();

    public LoadStudents(String inputFile)
    {

        this.inputFile = inputFile;
    }
    public List<Object> getFromFile()
    {
        try
        {
            BufferedReader in = new BufferedReader(new FileReader(inputFile));
            try
            {
                String line =  "";

                while(in.readLine() != null)
                {
                    line = in.readLine();
                    info.add(line);

                }


            }
            catch(IOException e)
            {
                System.err.println("Exception, man");
            }
            finally
            {
            in.close();
            }
        }
        catch(FileNotFoundException e)
        {
            System.err.println("File wasnt found ");
        }
        catch(IOException e)
        {
            System.err.println("Exception, man");
        }
        return info;
    }

}


import java.util.*;
public class Students
{
    public Students()
    {

    }
    public void printer()
    {
        List<Object> info = (new LoadStudents()).getFromFile();
        for (int x = 0; x<info.size(); x++)
        {
            System.out.println(info.get(x));
        }
    }

}

the Students class isnt finished but I am trying to figure out how to read the list from other classes. I have done research and have seen 3 similar problems, but they there is still something I'm missing because I keep getting the error

.\Students.java:11: error: constructor Load in class Load cannot be applied to g
iven types;
                List<Object> info = (new LoadStudents()).getFromFile();
                                     ^
  required: String
  found: no arguments
  reason: actual and formal argument lists differ in length
1 error

I understand it wants input, but I want it to use the previous input the user gives it when he inputs the command "input [whateverfile]". Can anyone tell me how I can call that list my Load class produces to any other class?


Solution

  • There are many ways to do this. My suggestion is that your Load class should be a factory that actually creates a list of Student from the file, and not a list of strings.

    Here are more suggestions:

    • Load class could have all methods statics and it could be non-instantiable. The fields you have in this class are useless after the file is read, you can just pass them to the static method as parameters.
    • Load is not a nice name for that class. LoadStudents is more meaningful, or even better StudentFactory.
    • Load and Student probably don't need to be public, package-private are be enough. Same for all the methods in these classes. Always use the lowest visibility possible.
    • data() is not a nice name for that method either. Something like getStudents(), or if you follow above advice, getFromFile(), is more meaningful.
    • Always print/log the stacktrace of the exceptions, otherwise you won't even know what/where it happened.
    • Instead of making the user type the whole commands, put a number on each option and let user select by number, that's faster to type and you avoid typo errors as well.
    • Only import the classes you're actually working with and not the whole package, that will make the compilation faster (unless you're importing a lot of classes from that package, which is not the case here).

    EDIT: since you still don't understand what I mean, here's an example:

    class StudentFactory {
    
        private static List<Student> listCache = new ArrayList<>();
    
        static List<Student> getStudents(final String filePath) {
            if (listCache.isEmpty() {
                BufferedReader in = null;
                try {
                    in = new BufferedReader(new FileReader(filePath));
                    String line;
                    while((line = in.readLine()) != null) {
                        // Parse the line and create a Student instance from it, then add it to the list
                        listCache.add(student);
                    }
                } catch(IOException e) {
                    System.err.println("Exception, man");
                    e.printStackTrace();
                } catch(FileNotFoundException e) {
                    System.err.println("File wasnt found ");
                    e.printStackTrace();
                } finally {
                    if (in != null) in.close();
                }
            }
            return listCache;
        }
    
        private StudentFactory() {
            // Avoid instantiation
        }
    }
    

    Then you can just do

    final List<Student> listOfStudents = StudentFactory.getStudents(filePath);
    

    from anywhere in your code to get a list of students. filePath can be null if you already passed it previously.