Java Object-Oriented Student Management System

This document presents a foundational Java application demonstrating object-oriented programming (OOP) principles through a simple university student management system. It showcases inheritance, polymorphism, and class design to manage different types of students: undergraduates, graduates, and alumni.

Core Class Definitions

The system is built upon a hierarchy of classes, starting with an abstract Student class, which defines common attributes and behaviors for all student types. Specific student categories then extend this base class, implementing or overriding methods as needed.

The Student Abstract Class

The Student class serves as the abstract base for all student types. It encapsulates common properties like name and id, and defines abstract methods that must be implemented by its subclasses, ensuring a consistent interface across different student categories. It also includes a placeholder save method for data persistence.


public abstract class Student {
    protected String name;
    protected int id;

    public Student(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public abstract String type(); // Returns the type of student (e.g., "undergraduate", "graduate", "alumni")
    public abstract String toString(); // Provides a string representation of the student object

    // Placeholder for saving student data. In a real application, this would handle file I/O.
    public void save(String filename) {
        System.out.println("Attempting to save data for " + name + " (ID: " + id + ") to " + filename + ".");
    }
}

The Undergraduate Class

The Undergraduate class extends Student, adding specific attributes like graduationYear and a list of courses. It implements methods relevant to undergraduate students, such as displaying their level and registering for courses.


class Undergraduate extends Student {
    private int graduationYear;
    private ArrayList<String> courses;

    public Undergraduate(String name, int id, int graduationYear) {
        super(name, id);
        this.graduationYear = graduationYear;
        this.courses = new ArrayList<>();
    }

    public void displayStudentLevel() {
        System.out.println(name + " is an undergraduate student.");
    }

    public void registerCourses() {
        Random rand = new Random();
        int numCourses = rand.nextInt(5) + 1; // Registers between 1 and 5 courses
        for (int i = 1; i <= numCourses; i++) {
            courses.add("Course" + i);
        }
        System.out.println(name + " whose ID is: " + id + " started at AUS in " + graduationYear + ".");
        System.out.println(name + " is registered in " + numCourses + " course(s).");
    }

    @Override
    public String type() {
        return "undergraduate";
    }

    @Override
    public String toString() {
        return name + " Undergraduate ID: " + id + " Grad Year: " + graduationYear;
    }
}

The Graduate Class

Similar to Undergraduate, the Graduate class extends Student. It includes additional information such as whether the student completed their undergraduate studies at the same university (sameUniversity). It also provides its own implementations for displaying student level and course registration.


class Graduate extends Student {
    private int graduationYear;
    private boolean sameUniversity;
    private ArrayList<String> courses;

    public Graduate(String name, int id, int graduationYear, boolean sameUniversity) {
        super(name, id);
        this.graduationYear = graduationYear;
        this.sameUniversity = sameUniversity;
        this.courses = new ArrayList<>();
    }

    public void displayStudentLevel() {
        System.out.println(name + " is a graduate student." +
                (sameUniversity ? " They also did their undergraduate studies at the same university." :
                                " However, they did their undergraduate studies at a different university."));
    }

    public void registerCourses() {
        Random rand = new Random();
        int numCourses = rand.nextInt(5) + 1; // Registers between 1 and 5 courses
        for (int i = 1; i <= numCourses; i++) {
            courses.add("Course" + i);
        }
        System.out.println(name + " whose ID is: " + id + " started at AUS in " + graduationYear + ".");
        System.out.println(name + " is registered in " + numCourses + " course(s).");
    }

    @Override
    public String type() {
        return "graduate";
    }

    @Override
    public String toString() {
        return name + " Graduate ID: " + id + " Grad Year: " + graduationYear;
    }
}

The Alumni Class

The Alumni class represents former students. It extends Student and includes details like admissionYear, graduationYear, and their current employer. It provides overloaded constructors to handle cases where the employer information might not be immediately available.


class Alumni extends Student {
    private int graduationYear;
    private int admissionYear;
    private String employer;

    public Alumni(String name, int id, int admissionYear, int graduationYear) {
        super(name, id);
        this.admissionYear = admissionYear;
        this.graduationYear = graduationYear;
        this.employer = null; // Default to null if employer is not provided
    }

    public Alumni(String name, int id, int admissionYear, int graduationYear, String employer) {
        super(name, id);
        this.admissionYear = admissionYear;
        this.graduationYear = graduationYear;
        this.employer = employer;
    }

    @Override
    public String type() {
        return "alumni";
    }

    @Override
    public String toString() {
        String empStatus = (employer == null || employer.equals("Unknown")) ? "not working." : ("works at " + employer + ".");
        return name + " whose ID is: " + id + " started at AUS in " + admissionYear + ".\n" +
               name + " is an alumni who graduated in " + graduationYear + ".\n" +
               name + " is currently " + empStatus;
    }
}

The University Class

The University class acts as a container for a collection of Student objects. It holds an ArrayList of students and the university’s name, providing a centralized point for managing the student body.


class University {
    private ArrayList<Student> students;
    private String univName;

    public University(ArrayList<Student> students, String univName) {
        this.students = students;
        this.univName = univName;
    }

    public String getUnivName() {
        return univName;
    }
}

System Driver and Demonstration

The Driver class contains the main method, which serves as the entry point for the application. It demonstrates how to instantiate various student types, add them to a University object, and then iterate through them, showcasing polymorphism by calling methods appropriate to each student’s actual type.


public class Driver {
    public static void main(String[] args) {
        // Instantiate different types of students
        Alumni a1 = new Alumni("Ben", 1, 1990, 1994);
        Alumni a2 = new Alumni("Pamela", 2, 2000, 2004, "Microsoft");
        Undergraduate s1 = new Undergraduate("Ahmed", 3, 2023);
        Undergraduate s2 = new Undergraduate("Salma", 4, 2024);
        Graduate s3 = new Graduate("Adam", 5, 2024, true);
        Graduate s4 = new Graduate("Zain", 6, 2024, false);

        // Create an ArrayList to hold all students
        ArrayList<Student> students = new ArrayList<Student>();
        students.add(a1);
        students.add(a2);
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);

        // Create a University instance
        University uni = new University(students, "AUS");

        System.out.println("Welcome the " + uni.getUnivName() + " students:");
        System.out.println();

        // Iterate through the students, demonstrating polymorphism
        for (Student s : students) {
            if (s.type().equals("undergraduate")) {
                Undergraduate u = (Undergraduate) s; // Downcasting
                u.displayStudentLevel();
                u.registerCourses();
            } else if (s.type().equals("graduate")) {
                Graduate g = (Graduate) s; // Downcasting
                g.displayStudentLevel();
                g.registerCourses();
            } else { // Alumni
                System.out.println(s.getName() + " is an alumni.");
            }
            System.out.println(s); // Calls the overridden toString() method
            System.out.println();
            s.save("students.txt"); // Calls the save method from the Student class
        }
    }
}

}

Conclusion

This Java application effectively demonstrates key OOP concepts such as inheritance and polymorphism through a practical student management scenario. By structuring the code with a clear class hierarchy, it allows for flexible and extensible management of diverse student types within a university system.