Full disclosure, this is homework, but only a very small part of an assignment that I can't figure out why it's not working. Here is the assignment text:
Create a CollegeStudent class. This class will contain data fields that hold a student's first name, last name, enrollment date, and projected graduation date, using the GregorianCalendar class for each date. Provide get() and set() methods for each field. Also provide a constructor that requires first and last names and enrollment date, and sets the project graduation date to exactly four years after enrolment. Save the class as CollegeStudent.java.
Create an interactive application that prompts the user for data for two CollegeStudent objects. Prompt the user for first name, last name, enrollment month, enrollment day, and enrollment year for each CollegeStudent, and then instantiate the objects. Display all the values, including the projected graduation dates. Save the application as TestCollegeStudent.java
I've been able to do everything it asks, except when I try to calculate the graduation date, it adds 4 years to the enrollment date value as well. Here is my CollegeStudent class:
import java.util.GregorianCalendar;
public class CollegeStudent {
String firstName;
String lastName;
GregorianCalendar enrollmentDate;
GregorianCalendar graduationDate;
// Constructor requiring first name, last name, and enrollment date
public CollegeStudent(String first, String last, GregorianCalendar enrollment) {
firstName = first;
lastName = last;
enrollmentDate = enrollment;
// Set graduationDate to enrollmentDate, then add 4 years
graduationDate = enrollment;
graduationDate.add(GregorianCalendar.YEAR, 4);
}
// Get and Set firstName
public void setFirstName(String first) {
firstName = first;
}
public String getFirstName() {
return firstName;
}
// Get and Set lastName
public void setLastName(String last) {
lastName = last;
}
public String getLastName() {
return lastName;
}
// Get and Set enrollmentDate
public void setEnrollmentDate(GregorianCalendar enrollment) {
enrollmentDate = enrollment;
}
public GregorianCalendar getEnrollmentDate(){
return enrollmentDate;
}
// Get and Set graduationDate
public void setGraduationDate(GregorianCalendar graduation) {
graduationDate = graduation;
}
public GregorianCalendar getGraduationDate() {
return graduationDate;
}
}
My TestCollegeStudent.java displays both the enrollmentDate and graduationDate and they both show the same date 4 years after the initial enrollmentDate entered by the user. If I remove the line where I added 4 years to the graduationDate, they both display as the initial enrollmentDate. I feel like I'm missing some very simple syntax issue, but I haven't been able to figure out what it is.
It is happening because of the following assignment inside the constructor:
graduationDate = enrollment;
This assignment makes graduationDate
reference to the same instance of Calendar
which is being referenced by enrollment
and therefore a change in the instance brought through any of the references will cause the result to be the same for both the references.
You can understand it with the following example:
import java.util.Calendar;
import java.util.GregorianCalendar;
public class Main {
public static void main(String[] args) {
Calendar enrollment = Calendar.getInstance();
Calendar graduationDate = enrollment;
System.out.println(enrollment.getTime());
System.out.println(graduationDate.getTime());
graduationDate.add(GregorianCalendar.YEAR, 4);
System.out.println(enrollment.getTime());
System.out.println(graduationDate.getTime());
}
}
Output:
Sat Jan 16 15:31:29 GMT 2021
Sat Jan 16 15:31:29 GMT 2021
Thu Jan 16 15:31:29 GMT 2025
Thu Jan 16 15:31:29 GMT 2025
In order to deal with this situation, graduationDate
needs to reference a copy (clone) of the instance being referenced enrollment
so that any changes brought through the reference, graduationDate
will only be applicable to the clone.
import java.util.Calendar;
import java.util.GregorianCalendar;
public class Main {
public static void main(String[] args) {
Calendar enrollment = Calendar.getInstance();
Calendar graduationDate = (Calendar)enrollment.clone();// You have to do this
System.out.println(enrollment.getTime());
System.out.println(graduationDate.getTime());
graduationDate.add(GregorianCalendar.YEAR, 4);
System.out.println(enrollment.getTime());
System.out.println(graduationDate.getTime());
}
}
Output:
Sat Jan 16 15:30:34 GMT 2021
Sat Jan 16 15:30:34 GMT 2021
Sat Jan 16 15:30:34 GMT 2021
Thu Jan 16 15:30:34 GMT 2025
By the way, the date-time API of java.util
and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
Check out Trail: Date Time for step-by-step tutorial and examples of using the java.time API (the modern date-time API).