Comparing two dates using Comparable interface - java

I am currently designing a GUI for a bank database application. In my GUI I have a "List accounts opened before" button that I am trying to code to list all of the accounts in the database in a text area that have dates before a date that the user inputs into a text field. I am very confused about the implementation behind a Comparable interface and how to correctly compare two dates in a array of objects. In my mind my ShowBefore methods logic is correct, however I think that is not the case and I do not know why. My problem is with the BankDatabase's showBefore() method, Date's compareTo() method, and the GUI's ShowAllActions button. Any help would be greatly appreciated. I receive
"Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at BankDatabase.showBefore(BankDatabase.java:234)
at TransactionManager.showAllAccountsActionPerformed(TransactionManager.java:474)
at TransactionManager.access$1200(TransactionManager.java:17)
at TransactionManager$13.actionPerformed(TransactionManager.java:202)
"
When I input any date into the gui.
*I only posted the bare minimum methods required
public class BankDatabase
{
private static final int GROW_SIZE = 2;
private static final int NOT_FOUND = -1;
private static final int ARRAY_SIZE = 100; //i added this
private Account[] bank;
private int num;
/**
default constructor
*/
public BankDatabase()
{
num = 0;
bank = new Account[ARRAY_SIZE];
}
public String showBefore( Date prevDate)
{
String temp = new String();
for ( int i = 0; i < size(); i++)
{
if ( bank[i].getDate().compareTo(prevDate) == -1 )
{
temp += bank[i].toString(); //
temp += "\n";
}
}
return temp;
}
import java.util.Calendar;
import java.util.StringTokenizer;
public class Date implements Comparable {
private int invalidCheck = 0;
private int day;
private int month;
private int year;
/**
Parameterized Constructor.
#param d date
*/
public Date(String d)
{
StringTokenizer st = new StringTokenizer(d, "/");
month = Integer.parseInt(st.nextToken());
day = Integer.parseInt(st.nextToken());
year = Integer.parseInt(st.nextToken());
}
/**
Copy Constructor.
#param d date
*/
public Date(Date d)
{
month = d.month;
day = d.day;
year = d.year;
}
/**
Creates an instance with todays date
*/
public Date()
{
Calendar c = Calendar.getInstance();
this.day = c.get(Calendar.DAY_OF_MONTH);
this.month = c.get(Calendar.MONTH) + 1;
this.year = c.get(Calendar.YEAR);
}
/**
Compare “this” with (Date) o; if “this” is before o, return -1; if “this” is equal
to o return 0; if “this” is after o, return 1.
#param o
#return the value of the date
*/
public int compareTo(Object o)
{
Date d = new Date((Date) o);
if(d.year > year)
return -1;
if(d.year < year)
return 1;
if(d.month > month)
return -1;
if(d.month < month)
return 1;
if(d.day > day)
return -1;
if(d.day < day)
return 1;
return 0;
}
/**
checks to see if certain dates are valid. Also checks
if it is a leap year to verify the correct amount of days
in February.
#return true if the date is valid, false otherwise
*/
public boolean isValid()
{
if (( month == Month.JAN || month == Month.MAR
|| month == Month.MAY || month == Month.JUL
|| month == Month.OCT || month == Month.OCT
|| month == Month.DEC )
&& ( day <= Month.DAYS_ODD && day > invalidCheck ) )
return true;
if (( month == Month.APR || month == Month.JUN
|| month == Month.SEP
|| month == Month.NOV )
&& ( day <= Month.DAYS_EVEN && day > invalidCheck ) )
return true;
boolean leapYear = false;
if ( year % Month.QUADRENNIAL == invalidCheck
|| year % Month.CENTENNIAL == invalidCheck
|| year % Month.QUATERCENTENNIAL == invalidCheck )
{
leapYear = true;
}
if (leapYear)
{
if (month == Month.FEB && day <= Month.DAYS_FEB + 1)
return true;
}
if (month == Month.FEB && day <= Month.DAYS_FEB)
return true;
return false;
}
/**
Return the name and date of the TeamMember as a String.
#return name::price as a string.
*/
public String toString()
{
return month + "/" + day + "/" + year;
}
/**
day,month, and year are equal if they have the
same day, month, and year
#param obj
#return true if they are equal, false otherwise.
*/
public boolean equals(Object obj)
{
if (obj instanceof Date)
{
Date d = (Date) obj;
return d.day == day && d.month == month && d.year == year;
}
return false;
}
}
public abstract class Account
{
private static int numAccount = 1000; //incremented by 1 for each acc op.
protected final int PERCENTAGE = 100;
protected final int MONTH_PER_YEAR = 12;
protected Profile holder; //account holder's profile
protected int accNumber; //a sequence number from numAccount
protected double balance;
protected Date openOn; //the date the account is opened on
/**
parameterized constructor
#param name String that will be the name
#param phone String that will be the phone associated with the account
*/
public Account(String name, String phone)
{
holder = new Profile(name, phone);
accNumber = numAccount++;
balance = 0;// 0 if deposit has to happen after
openOn = new Date();
}
public Date getDate()
{
return openOn;
}
public abstract String toString(); //subclass must implement this method
public class TransactionManager extends javax.swing.JFrame
{
BankDatabase database = new BankDatabase();
TransactionSimulator sim = new TransactionSimulator();
ButtonGroup accType = new ButtonGroup();
private Vector client;
/**
Creates new form TransactionManager
*/
public TransactionManager()
{
initComponents();
database = new BankDatabase();
accType.add(checking);
accType.add(savings);
accType.add(moneyMarket);
cbSpecialSavings.setEnabled(false);
client = new Vector<String>();
}
private void showAllAccountsActionPerformed(java.awt.event.ActionEvent evt)
{
Date openOn = new Date(dateBefore.getText());
outputArea.append(database.showBefore(openOn));
}

About your showBefore() at least make some additional checks
public String showBefore( Date prevDate)
{
StringBuilder builder = new StringBuilder("");
for ( int i = 0; i < size(); i++)
{
Account account = bank[i];
if (account != null) {
Date date = account.getDate();
if (date != null && date.compareTo(prevDate) == -1 ) {
builder.append(account.toString() + "\n")
}
}
}
return builder.toString();
}
and keep in mind what StringBuilder is not synchronized
In other case read more about Java 8 features such as Stream API, New Date/Time API, lambda
public String showBefore(LocalDate prevDate)
{
StringBuilder builder = new StringBuilder("");
Arrays.asList(bank).parallelStream().forEach(account -> {
if (account != null) {
LocalDate date = account.getDate();
if (date != null && date.compareTo(prevDate) == -1 ) {
builder.append(account.toString()).append("\n");
}
}
});
return builder.toString();
}

if(d.month > month)
return -1;
if(d.month > month)
return 1;
You have equivalent if clauses in equals method.

Related

Comparing two objects always returns false

I'm trying to create a simple date class. My professor also wants us to include our own .equals method in the date class which should compare two objects. My problem is my method returns false unless I compare the exact same object, even if their values are the same.
Here is my driver:
public class Lab3Driver {
public static void main(String[] args) {
Date theDate = new Date(6, 30, 1995);
Date anotherDate = new Date(6, 30, 1995);
System.out.println(theDate.equals(anotherDate));
System.out.println(theDate);
System.out.println(anotherDate);
}
}
Here is my date class:
public class Date {
private int month;
private int day;
private int year;
public Date() // default no arg constructor
{
this.month = 1; // set to date I completed this class, for fun.
this.day = 26;
this.year = 2019;
}
public Date(int m, int d, int y) // normal constructor in case you want to initialize variables upon object declaration
{
this.month = m;
this.day = d;
this.year = y;
}
public int getMonth() {
return month;
}
public void setMonth(int month)
{
if (month >= 1 && month <= 12) // if else that checks and makes sure months are between 1 and 12
{
this.month = month;
}
else
{
System.out.println("Invalid month input. Months are between 1 and 12.");
}
}
public int getDay()
{
return day;
}
public void setDay(int day)
{
if (day >= 1 && day <= 31) // if else that checks and makes sure days are between 1 and 31
{
this.day = day;
}
else
{
System.out.println("Invalid day input. Days are between 1 and 31.");
}
}
public int getYear()
{
return year;
}
public void setYear(int year) // year can be set to anything, in the case that this program is used for something
{ // other than the present day, as in a reference to the past or future
this.year = year;
}
public String toString() // to string in order to print out the date that is stored
{
String theDate = "The date is: " + this.month + "/" + this.day + "/" + this.year;
return theDate;
}
public boolean equals(Object that) // compares two objects and checks for null/type casting
{
if (this == that)
return true;
else if(that == null || that.getClass()!= this.getClass())
{
System.out.println("Null or type casting of argument.");
return false;
}
else
return false;
}
Something with this method is creating a problem I think:
public boolean equals(Object that) // compares two objects and checks for null/type casting
{
if (this == that)
return true;
else if(that == null || that.getClass()!= this.getClass())
{
System.out.println("Null or type casting of argument.");
return false;
}
else
return false;
}
It's normal, because you wrote
else {
return false;
}
So whenever that object has a different reference and is from the same class you go in the else statement above which returns false.
You should implement the code instead of returning false, for example:
public boolean equals(Object that) // compares two objects and checks for null/type casting
{
if (this == that)
return true;
else if(that == null || that.getClass()!= this.getClass())
{
System.out.println("Null or type casting of argument.");
return false;
}
else
return this.year == that.getYear() && ...;
}
if (this == that)
This line does not compare the objects. This only verifies if your object is in the same memory space, basically asking if it is exactly the same object (pointing to the same place).
If you want to compare two different objects, two different instances like
Date theDate = new Date(6, 30, 1995);
Date anotherDate = new Date(6, 30, 1995);
then you'll have to add more lines of code that check each value in each variable in each of the objects, or override the ' == ' method to make it compare the values.
Sοme οther things tο nοte:
As Nate has already said, yοu have tο cοmpare the individual fields οf the twο οbjects yοu are cοmparing. Tο dο that, yοu can use return year == that.getYear() && day == that.getDay() && mοnth == that.getMοnth().
But wait! Yοur equals methοd takes in an Object. Therefοre, we can't use thοse methοds. There are twο ways yοu can fix this.
Dο an instanceοf check at the beginning οf the methοd, and then cast the parameter tο a Date οbject.
Restrict the parameter οf yοur methοd tο οnly allοw Date οbjects.
Persοnally, I wοuld dο the latter, since an errοr will pοp up at cοmpile time if yοu used a nοn-Date οbject. Hοwever, if yοu did a type check in methοd and thrοw an exceptiοn if the type check failed, yοu may never nοtice an errοr if yοu prοvided an argument that is nοt a Date οbject until the method is called.
One thing you need to make sure that if you override the equals method you should also override the hashCode method.
For your reference, please read the section
https://www.baeldung.com/java-equals-hashcode-contracts#hashcode
I have completed both the overridden methods for you.
#Override
public boolean equals(Object that) {
if (this == that)
return true;
if(!(that instanceof Date))
return false;
if(that == null || that.getClass()!= this.getClass())
return false;
Date anotherDate = (Date) that;
if(this.month == anotherDate.month
&& this.day == anotherDate.day
&& this.year == anotherDate.year)
return true;
return false;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (month ^ (month >>> 16));
result = prime * result + (int) (day ^ (day >>> 16));
result = prime * result + (int) (year ^ (year >>> 16));
return result;
}

JAVA call factory methods implicitly

I have 1 constructor and 1 factory method for my Date class. The first one just have 3 int parameter represent month, day and year. And the second one, I provide it in case user give string as one parameter to represent month/day/year.
As you can see in the main(), I forget to call parseIt, the factory method. But compiler still provide correct result. So question is: can JAVA call this factory method implicitly?
Please take a look the 1st constructor and 2nd factory methods:
import java.io.*;
class Date {
private int month;
private int day;
private int year;
public Date(int month, int day, int year) {
if (isValidDate(month, day, year)) {
this.month = month;
this.day = day;
this.year = year;
} else {
System.out.println("Fatal error: Invalid data.");
System.exit(0);
}
}
public static Date parseIt(String s) {
String[] strSplit = s.split("/");
int m = Integer.parseInt(strSplit[0]);
int d = Integer.parseInt(strSplit[1]);
int y = Integer.parseInt(strSplit[2]);
return new Date(m, d, y);
}
public static boolean isLeapYear(int year) {
if (year%4 != 0) {
return false;
} else if (year%100 == 0 && year%400 != 0) {
return false;
}
return true;
}
public static int daysInMonth(int month, int year) {
if (month == 2) {
if (isLeapYear(year)) {
return 29;
} else {
return 28;
}
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else {
return 31;
}
}
public static boolean isValidDate(int month, int day, int year) {
if (year < 1 || year > 9999 || month <= 0 || month > 12 || day <= 0) {
return false;
} else if (day > daysInMonth(month, year)) {
return false;
}
return true;
}
public static void main(String[] argv) {
Date d1 = new Date(1, 1, 1);
System.out.println("Date should be 1/1/1: " + d1);
d1 = new Date("2/4/2");
System.out.println("Date should be 2/4/2: " + d1);
}
}
No, it will not. There is no constructor which takes in a string, so it would throw a syntax error. In order to make it work, you would have to define a constructor which takes in a String parameter performs the same logic as the parseIt(String) function.

Junit Confusion

I am trying to test the day class using Junit Testing. This method is the method I am struggling with.
public Day previousDay() {
int y = year;
int m = month;
int d = date;
if (y == GREGORIAN_START_YEAR && m == GREGORIAN_START_MONTH
&& d == GREGORIAN_START_DAY)
d = JULIAN_END_DAY;
else if (d > 1)
d--;
else
{
m--;
if (m < JANUARY)
{
m = DECEMBER;
y--;
if (y == 0)
y--;
}
d = daysPerMonth(y, m);
}
return new Day(y, m, d);
}
This is what I have so far
public class DayTest extends TestCase
{
/**
* Test the constructor
*/
public void testDay()
{
//calling
Day today = new Day(2015,2,14);
assertEquals(2015,today.getYear());
assertEquals(2,today.getMonth());
assertEquals(14,today.getDate());
}
public void testAddDays()
{
Day today = new Day(2015,2,14);
int n = 5;
Day otherDay = today.addDays(n);
assertTrue(otherDay.daysFrom(today) == n);
}
public void testPreviousDays()
{
Day today = new Day(2015,2,14);
today.previousDay();
assertEquals(13,today.getDate());
}
public void testLeapYear()
{
Day today = new Day(2015,2,14);
assertEquals(today.isLeapYear(2015),false);
}
}
The other tests went smoothly but this test for previousday() is giving me trouble. When I call previousDay() it doesn't seem to work at all. I am confused why when the other tests worked fine. Any help would be appreciated!
You probably mean:
today = today.previousDay()
Right now you're ignoring the return value of the function.

How to make text from textfile into fields of an object

Okay, so I get a text file, tokenize it, and then try to write it to another file.
I have a class called course which has 4 parameters: name, level, code, year
I have divided each line of the text file onto a different line
#Edit: Should have mentioned this earlier, but I have 3000 courses stored in a text file
public void readFromFile() throws IOException
{
int index = 0;
int j = -1;
int spaceCount = 0;
courseNumber++;
setCourseFields();
BufferedReader inputFile = new BufferedReader(new FileReader(INPUT_FILE));
PrintWriter outputFile = new PrintWriter(new FileWriter(OUTPUT_FILE));
String lineOfText = inputFile.readLine();
while (lineOfText != null)
{
outputFile.println(lineOfText);
lineOfText = inputFile.readLine();
for (char c : lineOfText.toCharArray())
{
if (c == ' ')
{
spaceCount++;
}
}
if(spaceCount == 1)
{
delimiter = DELIMITER_SPACE;
}
else if(spaceCount == 2)
{
delimiter = DELIMITER_TAB;
}
System.out.println("Course" + courseNumber + "\n");
// for each token in the string
while ((j = lineOfText.indexOf(delimiter, (index = ++j))) != -1)
{
System.out.println(courseField[k] + ": " + lineOfText.substring(index, j));
counter++;
k++;
}
// extract the last token
if (index > 0)
{
System.out.println("Year: " + lineOfText.substring(index));
++courseNumber;
}
if(k == 3)
{
k = k - k;
index = 0;
}
delayDisplay();
} // while(lineOfText != null)
inputFile.close();
outputFile.close();
}
And then I'd get something like this
Course1
Name: Computer Engineering Technology
Level: IB
Code: TEJ4M
Year: 2017
Course2
Name: Communications Technology
Level: Special Education
Code: TGJ2O
Year: 2002
Each course is unique, and I need help so that I can assign each of the above strings to a variable.
Each course has 4 instance fields + a unique serial number(Course Number)
The 4 fields are:
String name;
char level;
String code;
int academicYear;
I want to make courses out of each of the 4 lines
Here is my course class
public class Course extends Object implements Serializable
{
// class constants
public static final String DEFAULT_CODE = "AAA10";
public static final char DEFAULT_LEVEL = 'X';
public static final String DEFAULT_NAME = "unassigned";
public static final int DEFAULT_YEAR = 1900;
private static final char ACADEMIC_LEVEL = '1';
private static final char ENGLISH_LANGUAGE_LEARNERS_LEVEL = '9';
private static final int ERROR_CODE = -1;
private static final char IB_LEVEL = '7';
private static final int MAXIMUM_YEAR = 2014;
private static final int MINIMUM_YEAR = 1900;
private static final char SPECIAL_EDUCATION_LEVEL = '8';
// instance variables
private int academicYear;
private String code;
private static int counter = 0;
private char level;
private String name;
private int serialNumber;
/**
* Constructs a course with default characteristics.
*/
public Course()
{
this.academicYear = DEFAULT_YEAR;
this.code = DEFAULT_CODE;
this.level = DEFAULT_LEVEL;
this.name = DEFAULT_NAME;
serialNumber = ++counter;
} // end of constructor Course()
/**
* Constructs a course with the specified characteristics.
*
* #param name - the Ministry-assigned name of this course;
* ex: Introduction to Computer Science
* #param code - the Ministry-assigned code of this course; ex: ICS3U
* #param level - one of the enumerated levels ex: '7', '1', '9', '8'
* #param academicYear - a 4-digit year of the Gregorian calendar
* set between a minimum and maximum year
*/
public Course(String name, String code, char level, int academicYear)
{
if(name == null)
{
this.name = DEFAULT_NAME;
}
else
{
this.name = name;
} // end of if(name == null)
if(code == null)
{
this.code = DEFAULT_CODE;
}
else
{
this.code = code;
} // end of if(code == null)
if (level == IB_LEVEL || level == ACADEMIC_LEVEL
|| level == ENGLISH_LANGUAGE_LEARNERS_LEVEL
|| level == SPECIAL_EDUCATION_LEVEL)
{
this.level = level;
}
else
{
this.level = DEFAULT_LEVEL;
} // end of if (level == IB_LEVEL || level == ACADEMIC_LEVEL || level ==
ENGLISH_LANGUAGE_LEARNERS_LEVEL || level == SPECIAL_EDUCATION_LEVEL )
if (academicYear >= MINIMUM_YEAR && academicYear <= MAXIMUM_YEAR)
{
this.academicYear = academicYear;
}
else
{
this.academicYear = DEFAULT_YEAR;
} // end of (academicYear >= MINIMUM_YEAR && academicYear <= MAXIMUM_YEAR)
serialNumber = ++counter;
} // end of constructor Course(String name, String code, char level, int academicYear)
/* Comparison methods*/
/**
* Indicates whether another object has a state identical to this object’s state.
*
* #param otherCourse - the object whose state is compared to this object’s
*
* #return true if the other object has an identical state; otherwise false
*/
public boolean equals(Object otherCourse)
{
if(otherCourse == null) return false;
if (this.getClass() != otherCourse.getClass()) return false;
if (this == otherCourse) return true;
// Typecasting Object otherCourse into a Course to compare objects' states
Course course1 = (Course) otherCourse;
if(serialNumber != course1.getSerialNumber()) return false;
if(academicYear != course1.getYear()) return false;
if(level != course1.getLevel()) return false;
if(code != course1.getCode()) return false;
if(name != course1.getName()) return false;
// needed to satisfy the compiler
return true;
} // end of method boolean equals(Object course)
/**
* Indicates whether another object has a state identical to this object’s state,
* ignoring each object's unique serial number.
*
* #param otherCourse - the object whose state is compared to this object’s
*
* #return true if the other object has an identical state; otherwise false
*/
public boolean equalsIgnoreSerial(Object otherObject)
{
if(otherObject == null) return false;
if (this.getClass() != otherObject.getClass()) return false;
boolean courseEquals;
Course anotherCourse = (Course) otherObject;
// Ignore unique serial number of each course
if(this.serialNumber == anotherCourse.getSerialNumber()) return false;
if(this.academicYear != anotherCourse.getYear()) return false;
else courseEquals = true;
if(this.level != anotherCourse.getLevel()) return false;
else courseEquals = true;
if(this.code != anotherCourse.getCode()) return false;
else courseEquals = true;
if(this.name != anotherCourse.getName()) return false;
else courseEquals = true;
return courseEquals;
} // end of method boolean equalsIgnoreSerial(Object course
/**
* Compares this Course to another.
*
* #return a negative value, if this course should come before the other course;
* 0, if this course and the other course have equal states;
* a positive value if this course should come after the other course
*/
public int compareTo(Course otherCourse)
{
int before = -1;
int after = 1;
int equals = 0;
int resultCode = code.compareTo(otherCourse.getCode());
int resultName = name.compareTo(otherCourse.getName());
if(otherCourse == null) return -1;
if(this.equals(otherCourse)) return equals;
if(serialNumber < otherCourse.getSerialNumber()) return before;
if(serialNumber > otherCourse.getSerialNumber()) return after;
if(academicYear < otherCourse.getYear()) return before;
if(academicYear > otherCourse.getYear()) return after;
if(!(sortLevel(level) == -1 || sortLevel(otherCourse.getLevel()) == -1))
{
if(sortLevel(level) < sortLevel(otherCourse.getLevel())) return before;
if(sortLevel(level) > sortLevel(otherCourse.getLevel())) return after;
} // end of if(!(sortLevel(level) == -1 || sortLevel(otherCourse.getLevel()) ==
-1))
if(code.compareTo(otherCourse.getCode()) != 0) return resultCode;
if(name.compareTo(otherCourse.getName()) != 0) return resultName;
// neccessary to satisfy the compiler
return 5;
} // end of public int compareTo(Course otherCourse)
/* utility methods*/
public static int sortLevel(char level)
{
/*************************************
final char[] LEVEL = {'7', '1', '9', '8'};
for (int index = 0; index < LEVEL.length; index++)
{
if(LEVEL[index] == level) return index;
if(LEVEL[index] != level) return ERROR_IO_EXCEPTION;
} // end of for (int index = 0; index < LEVEL.length; index++)
// error code for not found, should not be reached
return -1;
****************************************/ //code taken from in class discussion
final char[] LEVEL = {'7', '1', '9', '8'};
for (int index = 0; index < LEVEL.length; index++)
{
if(LEVEL[index] == level) return index;
if(LEVEL[index] != level) return -1;
} // end of for (int index = 0; index < LEVEL.length; index++)
// error code for not found, should not be reached
return ERROR_CODE;
} // end of public static int sortLevel(char level)
/* accessors*/
/**
* Returns the code of this course.
*
* #returns Returns the code of this course
*/
public String getCode()
{
return code;
} // end of method getCode()
/**
* Returns the level of this course.
*
* #return the level of this course
*/
public char getLevel()
{
return level;
} // end of method getLevel()
/**
* Returns the name of this course.
*
* #return the name of this course.
*/
public String getName()
{
return name;
} // end of method getName()
/**
* Returns the unique serial number of this course.
*
* #return the unique serial number of this course.
*/
public int getSerialNumber()
{
return serialNumber;
} // end of method getSerialNumber()
/**
* Returns the academic year of this course.
*
* #return the 4-digit academic year of this course
*/
public int getYear()
{
return academicYear;
} // end of method getYear()
/* mutators */
/**
* Sets the code of this course.
*
* #param newCode - the new code of this course.
*/
public void setCode(String newCode)
{
if (newCode == null) return;
this.code = newCode;
} // end of method setCode(String newCode)
/**
* Sets the level of this course.
*
* #param newLevel - one of the enumerated levels
*/
public void setLevel(char newLevel)
{
if(newLevel == IB_LEVEL || newLevel == ACADEMIC_LEVEL || newLevel ==
ENGLISH_LANGUAGE_LEARNERS_LEVEL || newLevel == SPECIAL_EDUCATION_LEVEL)
{
level = newLevel;
}
else
{
level = DEFAULT_LEVEL;
} // end of if(newLevel == IB_LEVEL || newLevel == ACADEMIC_LEVEL || newLevel ==
ENGLISH_LANGUAGE_LEARNERS_LEVEL || newLevel == SPECIAL_EDUCATION_LEVEL)
} // end of method setLevel(char newLevel)
/**
* Sets the name of this course.
*
* #param newName - the new name of this course
*/
public void setName(String newName)
{
if (newName == null) return;
this.name = newName;
} // end of method setName(String newName)
/**
* Sets the academic year of this course.
*
* #param newYear - the new 4-digit academic year of this course
*/
public void setYear(int newYear)
{
if (newYear >= MINIMUM_YEAR && newYear <= MAXIMUM_YEAR)
{
this.academicYear = newYear;
}
else
{
academicYear = DEFAULT_YEAR;
} // end of if (newYear >= MINIMUM_YEAR && newYear <= MAXIMUM_YEAR)
} // end of method setYear(int newYear)
/**
* Returns a string representation of this course.
*
* #override toString in class Object
*
* #return a string representation of this course.
*/
public String toString()
{
return
this.getClass().getName()
+"["
+ "Serial Number: " + serialNumber
+ ", academic year: " + academicYear
+ ", level: " + level
+ ", code: " + code
+ ", name: " + name
+"]";
} // end of String toString()
Also, I need help converting the string into a char for level and into an int for academic year, any ideas
Here is my CourseUtility class, which is not finished yet
public class CourseUtility
{
// class constants
private static final String INPUT_FILE = "courses.text";
private static final String OUTPUT_FILE = "CoursesTokenized.text";
private static int counter = 0;
private static int courseNumber = 0;
private static int k = 0;
private static final String DELIMITER_SPACE = " ";
private static final String DELIMITER_TAB = "\t";
String delimiter = DELIMITER_TAB;
private static final String DEFAULT_LEVEL = "X";
String name = "";
String code = "";
String year = "";
String level = "";
String lineOfText;
private static String[] courseField = new String[5];
/**
* Constructor for objects of class CourseUtility
*/
public CourseUtility() throws IOException
{
}
public void readFromFile() throws IOException
{
int index = 0;
int j = -1;
int spaceCount = 0;
courseNumber++;
setCourseFields();
BufferedReader inputFile = new BufferedReader(new FileReader(INPUT_FILE));
PrintWriter outputFile = new PrintWriter(new FileWriter(OUTPUT_FILE));
String lineOfText = inputFile.readLine();
while (lineOfText != null)
{
for (char c : lineOfText.toCharArray())
{
if (c == ' ')
{
spaceCount++;
}
}
if(spaceCount == 1)
{
delimiter = DELIMITER_SPACE;
}
else if(spaceCount == 2)
{
delimiter = DELIMITER_TAB;
}
System.out.println("Course" + courseNumber);
// for each token in the string
while ((j = lineOfText.indexOf(delimiter, (index = ++j))) != -1)
{
System.out.println(courseField[k] + ": " + lineOfText.substring(index, j));
System.out.println("");
outputFile.println(lineOfText.substring(index, j));
counter++;
k++;
}
// extract the last token
if (index > 0)
{
System.out.println("Year: " + lineOfText.substring(index));
outputFile.println(lineOfText.substring(index));
++courseNumber;
}
// for each token in the string
// Course c = new Course(hm.get("Name"), hm.get("Code"),
hm.get("Level"), Integer.parseInt(hm.get("Year")) );
// System.out.println(c);
if(k == 3)
{
k = k - k;
index = 0;
}
delayDisplay();
lineOfText = inputFile.readLine();
} // while(lineOfText != null)
inputFile.close();
outputFile.close();
}
public CourseUtility(String name, String code, String level, String year)
{
if(name == null)
{
this.name = Course.DEFAULT_NAME;
}
else
{
this.name = name;
} // end of if(name == null)
if(code == null)
{
this.code = Course.DEFAULT_CODE;
}
else
{
this.code = code;
} // end of if(code == null)
if(level == null)
{
this.level = DEFAULT_LEVEL;
}
else
{
this.level = level;
} // end of if(level == null)
if(year == null)
{
this.year = null;;
}
else
{
this.year = year;
} // end of if(year == null)
}
private void delayDisplay()
{
try
{
Thread.sleep(1000);
} catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
} // end of try
} // end of method void delayDisplay()
private void convertLevel(String courseLevel)
{
level = DEFAULT_LEVEL;
if(level == "IB") level = "7";
if(level == "Academic")level = "1";
if(level == "Applied") level = "1";
if(level == "ELL") level = "9";
if(level == "Special Education") level = "8";
} // end of method convertLevel(String courseLevel)
public void deleteCourse()
{
private void setCourseFields()
{
courseField[0] = "Name";
courseField[1] = "Level";
courseField[2] = "Code";
courseField[3] = "Year";
} // end of method setCourseFields()
}
I think I see your problem. You are parsing the fields, but not saving them. One thing you can do is save the fields once you have them. Store them in a HashMap, where the key is the name of the field. Then use your HashMap to retrieve the fields and call the constructor:
// for each token in the string
HashMap<String,String> hm = new HashMap<String,String>(); //NEW
while ((j = lineOfText.indexOf(delimiter, (index = ++j))) != -1)
{
hm.put(courseField[k], lineOfText.substring(index, j)); //NEW
System.out.println(courseField[k] + ": " + lineOfText.substring(index, j));
counter++;
k++;
}
// extract the last token
if (index > 0)
{
System.out.println("Year: " + lineOfText.substring(index));
hm.put("Year", lineOfText.substring(index)); //NEW
++courseNumber;
}
//translate level string to a character
char lvl;
String sLevel = hm.get("Level");
if (sLevel.equals("IB"))
lvl = '7';
else if (sLevel.equals("Special Education"))
lvl = '8';
else if (sLevel.equals("Academic"))
lvl = '8';
else if (sLevel.equals("English Language Learners"))
lvl = '1';
else
lvl = ' '; /* unknown level */
//create the Course object
Course c = new Course(hm.get("Name"), hm.get("Code"), lvl , Integer.parseInt(hm.get("Year")) );

Calling toString method from other class's toString. Not reurning values [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
why am i getting the following error message when i call the toString of class Date from toString of class Time2 ?
Exception in thread "main" java.lang.NullPointerException
at Exerciseschpt8.Time2.toString(Time2.java:111)
at Exerciseschpt8.Time2Test.main(Time2Test.java:18)
package Exerciseschpt8;
public class Date{
private int month; // 1-12
private int day; // 1-31 based on month
private int year; // any year
public Date(){
this(0,0,0);
}
public Date(int theMonth, int theDay, int theYear) {
month = checkMonth(theMonth); // validate month
year = theYear; // could validate year
day = checkDay(theDay); // validate day
System.out.printf("Date object constructor for date %s\n", this);
}
private int checkMonth(int month) {
if (month > 0 && month <= 12) // validate month
return month;
else // month is invalid
{
System.out.printf("Invalid month (%d) set to 1.", month);
return 1; // maintain object in consistent state
} // end else
} // end method checkMonth
// utility method to confirm proper day value based on month and year
private int checkDay(int day) {
int[] daysPerMonth = { 0, 31, 28, 31, 30, 31, 30, 28, 31, 30, 31, 30,
31 };
// check if day in range for month
if (day > 0 && day <= daysPerMonth[month])
return day;
// check for leap year
if (month == 2 && day == 29
&& (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)))
return day;
System.out.printf("Invalid day (%d) set to 1.", day);
return 1; // maintain object in consistent state
} // end method checkDay
// return a String of the form month/day/year
public String toString() {
return ""+month+"/"+ day+"/"+year;
} // end method toString
public int nextDay() {
int testDay = day + 1;
if (checkDay(testDay) == testDay)
day = testDay;
else {
day = 1;
//nextMonth();
}
return day;
}
public int nextMonth() {
if (1 == month)
month++;
return month = 1;
}
public String toDateString() {
return month + "/" + day + "*/" + year;
}
}
package Exerciseschpt8;
import Exerciseschpt8.Date;
public class Time2 {
Date dateX;
private int hour; // 0 - 23
private int minute; // 0 - 59
private int second; // 0 - 59
public Time2() {
this(0, 0, 0);
}
public Time2(int h) {
this(h, 0, 0);
}
public Time2(int h, int m) {
this(h, m, 0);
}
public Time2(int h, int m, int s) {
setTime(h, m, s);
}
public Time2(Time2 time) {
this(time.getHour(), time.getMinute(), time.getSecond());
}
public boolean setTime(int h, int m, int s) {
boolean hourValid, minuteValid, secondValid;
hourValid = setHour(h); // set the hour
minuteValid = setMinute(m); // set the minute
secondValid = setSecond(s); // set the second
return (hourValid && minuteValid && secondValid);
}
public boolean setHour(int h) {
// hour = ((h >= 0 && h < 24) ? h : 0);
if (h >= 0 && h < 24) {
hour = h;
return true;
} else {
hour = 0;
return false;
}
} // end method setHour
public boolean setMinute(int m) {
// minute = ((m >= 0 && m < 60) ? m : 0);
if (m >= 0 && m < 60) {
minute = m;
return true;
} else {
minute = 0;
return false;
}
} // end method setMinute
public boolean setSecond(int s) {
// second = ((s >= 0 && s < 60) ? s : 0);
if (s >= 0 && s < 60) {
second = s;
return true;
} else {
second = 0;
return false;
}
} // end method setSecond
public int getHour() {
return hour;
} // end method getHour
public int getMinute() {
return minute;
} // end method getMinute
public int getSecond() {
return second;
} // end method getSecond
// Tick the time by one second
public void tick() {
setSecond(second + 1);
if (second == 23)
incrementMinute();
}
public void incrementMinute() {
setMinute(minute + 1);
if (minute == 25)
incrementHour();
}
public void incrementHour() {
setHour(hour + 1);
if (hour == 0)
dateX.nextDay();
}
public String toString() {
return + hour + ":" + minute + ":" + second + "\n"+dateX.toString();
}
package Exerciseschpt8;
public class Time2Test {
public static void main(String[] args) {
Time2 t1 = new Time2(2,15,23); // 00:00:00
/
Date d1 = new Date(10,23,1973);
//System.out.println(d1.toDateString());
System.out.println("Constructed with:");
System.out.println("t1: all arguments defaulted");
//System.out.printf(" %s\n", t1.toUniversalString());
System.out.printf(" %s\n", t1.toString());
}
}
You are nowhere initializing dateX in your Time2 class and using a method on it (dateX.toString()) in the toString() method of Time2 class. That is causing the valid NullPointerException.
To fix the issue, intialize dateX as appropriate to your program.
In the line Date dateX; you are declaring dateX, but you aren't initializing it, so it's a null pointer. To initialize it, change the line to Date dateX = new Date();

Categories

Resources