Java ClassCastException error with Comparable interface despite implementation - java

I'm working on a class assignment that accepts last name, first name and score for one or more students, stores them in an array and then sorts alphabetically by last name (or first name if last name is the same).
We're required to use a Student class that implements the Comparable interface.
As soon as I get to the Arrays.sort portion of the code, I get a ClassCastException stating that "Student cannot be cast to java.lang.Comparable".
I've searched and reviewed, tried to use implements Comparable<Student>, Clean and Build, but the error persists. Any help or hints are appreciated.
the error:
Exception in thread "main" java.lang.ClassCastException:
studentscoreapp.Student cannot be cast to java.lang.Comparable
at java.util.Arrays.mergeSort(Arrays.java:1144)
at java.util.Arrays.sort(Arrays.java:1079)
at studentscoreapp.StudentScoreApp.main(StudentScoreApp.java:35)
Java Result: 1 BUILD SUCCESSFUL (total time: 12 seconds)
Here's my Student class:
public class Student implements Comparable
{
private String lastName;
private String firstName;
private int score;
public Student(String fName, String lName, int s)
{
fName = firstName;
lName = lastName;
s = score;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public int getScore()
{
return score;
}
public void setScore(int score)
{
this.score = score;
}
#Override
public int compareTo(Object obj)
{
Student sent = (Student) obj;
if (sent.lastName.equals(this.lastName))
{
return this.firstName.compareToIgnoreCase(sent.firstName);
}
else return this.lastName.compareToIgnoreCase(sent.lastName);
}
#Override
public String toString()
{
return lastName + firstName + score;
}
}
the Comparable interface:
public interface Comparable
{
int compareTo(Object obj);
}
and my main:
import java.util.Arrays;
public class StudentScoreApp
{
public static void main(String[] args)
{
String firstName;
String lastName;
int score;
System.out.println("Welcome to the Student Scores Application");
int numStudents = Validation.getInt("Enter # of Students: ");
Student[] studentArray = new Student[numStudents];
int i;
for (i = 0; i < numStudents; i++)
{
firstName = Validation.getString("Student [" + (i + 1) + "] first name: ");
lastName = Validation.getString("Student [" + (i + 1) + "] last name: ");
score = Validation.getInt("Student [" + (i + 1) + "] score: ", 0, 100);
studentArray[i] = new Student(firstName, lastName, score);
}
Arrays.sort(studentArray); //line 35
System.out.println();
//take each obj of the array and print the student info
for (Student obj : studentArray)
{
System.out.println(obj.toString());
}
}
}

Arrays.sort() accepts an array of objects which are subtypes of java.lang.Comparable. In your code, you have created your own Comparable interface, which, while it behaves the same way as java.lang.Comparable, is not the same interface.

Related

How to write a method that reads particular content in an array lists and count the number of array's content

I am a new learner and I should create a method that will make this program work with no problems at all so I can get the :::final result that should look like this:::
3 is 3
Mark is Mark
Richard is Richard
Here is the code (PLEASE read the comments I wrote in the code)
public class Main {
/*I wrote the following method (Student) but I keep get some issues:
Please help I spend many days and I can't figure it out and I am runnung out
of time as I should understand the problem or at least the correction that I
can read and figure out what I was doing wrong.*/
// My written code starts here
public static String Student(String[] sx){
int counter = 0;
for (int i = 0; i < sx.length; i ++){
if (sx[i] != null) counter ++;
}
return counter;
sx = new String[counter];
}
// My written code ENDS here
// From this point I should preserve the code without any changes
static Student studentA;
static Student studentB;
static Student studentC;
public static void main(String[] args) {
studentA = new Student("Mark", "John", "Jimmy");
studentB = new Student("Will", "George", "Androw");
studentC = new Student("Frank", "Sam");
int totalStudents = Student.getTotalStudents();
System.out.println(totalStudents + " is 3");
System.out.println(studentA.getFirstName() + " is Mark");
studentA.setFirstName("Richard");
System.out.println(studentA.getFirstName() + " is Richard");
}
}
Check the following code snippet
import java.util.List;
public class Main {
// My written code starts here
static class Student {
String firstName;
String middleName;
String lastName;
// Constructor for setting the class variable with all 3 field
public Student(String firstName, String middleName, String lastName) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
// Constructor for setting the class variable with 2 field
public Student(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
//to get the FirstName field of a student object
public String getFirstName() {
return firstName;
}
//to set the FirstName field of a student object
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public static int getTotalStudents() {
// this is wrong way of doing this.
// You should ideally send a list Of Student to know the number of students as shown below
return 3;
}
public static int getTotalStudentsFromList(List<Student> studentList) {
return studentList.size();
}
}
// My written code ENDS here
// From this point I should preserve the code without any changes
static Student studentA;
static Student studentB;
static Student studentC;
public static void main(String[] args) {
studentA = new Student("Mark", "John", "Jimmy");
studentB = new Student("Will", "George", "Androw");
studentC = new Student("Frank", "Sam");
int totalStudents = Student.getTotalStudents();
System.out.println(totalStudents + " is 3");
System.out.println(studentA.getFirstName() + " is Mark");
studentA.setFirstName("Richard");
System.out.println(studentA.getFirstName() + " is Richard");
}
}
I have added possible comments to explain the code. Let me know if you feel any difficulty in understanding this.

Create method to count occurrences of type char within an array

I need to create a method that searches a String array whether a specfic character exists in the array and returns an integer of the number of occurrences the character appears, I have looked on other posts to try and work it out myself but they are all arrays of int not String
I have another class name hence the array name being type Name.
public class Reg {
//Fields
private ArrayList<Name> Name;
//Constructors
public Reg() {
Name = new ArrayList<>();
}
//Methods
public int CountCharacterOccurrences (Char character){
}
}
Name Class:
public class Name implements Comparable<Name> {
//Fields
private String firstName;
private String familyName;
//Constructors
public Name() {
firstName = "";
familyName = "";
}
public Name(String firstName, String familyName) {
this.firstName = firstName;
this.familyName = familyName;
}
//Methods
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setFamilyName(String familyName) {
this.familyName = familyName;
}
public String getFirstName() {
return firstName;
}
public String getFamilyName() {
return familyName;
}
public String getFullName() {
if (firstName.equals("") && familyName.equals("")) {
return "";
} else {
return firstName + " " + familyName;
}
}
#Override
public String toString() {
return "Name:[firstName=" + firstName + ", familyName=" + familyName + "]";
}
}
How do I add a method CountCharacterOccurences that accepts a char argument and returns an int signalling the number of occurrences.
Maybe this is what you mean:
class Reg{
private ArrayList<Name> names;
public Reg() {
names = new ArrayList<>();
}
public int countFirstNameOccurrences(char c) {
return names.stream() // get Stream<Name>
.map(Name::getFirstName) // convert Stream<Name> to Stream<String> using Name's firstName
.mapToInt(s -> s.length() - s.replace(String.valueOf(c), "").length()) // calculate every occurrence c in each firstName and get an IntStream
.sum(); // sum all the values
}
public static void main(String[] args) {
Reg reg = new Reg();
reg.names.add(new Name("John", "Doe"));
reg.names.add(new Name("Johnny ", "Doe"));
reg.names.add(new Name("Richard", "Roe"));
reg.names.add(new Name("James", "Roe"));
reg.names.add(new Name("Jane", "Roe"));
System.out.println(reg.countFirstNameOccurrences('J'));
}
}
Output:
4
as there are 4 J's in the first names in the list (John, Johnny, James and Jane)

Null values when printing out arrayList?

Hi I have created a toStringmethod in one of my classes which can be seen below.
Student Class:
package Practical5;
public class Student extends Person {
//instance variables
private static int MAX_MODULES = 6;
private StudentMode modeOfStudy;
private boolean studentLoan;
private int numEnrolledModules;
//constructor
public Student(String name, String dob, Address address, StudentMode modeOfStudy, boolean studentLoan) {
super(name, dob, address);
this.modeOfStudy = modeOfStudy;
this.studentLoan = studentLoan;
this.numEnrolledModules = 0;
}
//accessors & mutators
public StudentMode getMode() {
return modeOfStudy;
}
public boolean isStudentLoan() {
return studentLoan;
}
public int getNumEnrolledModules() {
return numEnrolledModules;
}
public void setMode(StudentMode modeOfStudy) {
this.modeOfStudy = modeOfStudy;
}
public void setStudentLoan(boolean studentLoan) {
this.studentLoan = studentLoan;
}
public void setNumEnrolledModules(int numEnrolledModules) {
this.numEnrolledModules = numEnrolledModules;
}
#Override
public void purchaseParkingPass() {
System.out.println(getName() + " just purchased a parking pass with student discount.");
}
#Override
public void addModule(String moduleCode) {
if (getNumEnrolledModules() < MAX_MODULES) {
System.out.println(getName() + " successfully registered for the module: " + moduleCode);
}
else {
System.out.println("You are unable to register for " + moduleCode + " as the maximum number of permitted module enrolments has been reached.");
}
}
public String toString() {
return "Student [ ID: " + getId() + "; Name: " + getName() +
"; DOB: " + getDob() + "; Study Mode: " + getMode() +
"; Number of Enrolled Modules: " + getNumEnrolledModules();
}
}
Person Class:
package Practical5;
public abstract class Person {
//instance variables
private static int LAST_ID = 1000 + 1;
private int id;
private String name;
private String dob;
private Address address;
//constructor
public Person(String name, String dob, Address address) {
super();
LAST_ID ++;
this.id = LAST_ID;
}
//accessors & mutators
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getDob() {
return dob;
}
public Address getAddress() {
return address;
}
public void setName(String name) {
this.name = name;
}
public void setDob(String dob) {
this.dob = dob;
}
public void setAddress(Address address) {
this.address = address;
}
//methods
public abstract void purchaseParkingPass();
public abstract void addModule(String moduleCode);
}
I then created a tester class and created a new ArrayList and added these elements to it.
I then created a for loop in order to loop through each element and call the toString method to print out the details of each element but it is returning null values.
Tester Class:
package Practical5;
import java.util.ArrayList;
import java.util.Scanner;
public class UIS_Tester {
public static void main(String[] args) {
Student student1 = new Student("James Black", "07/09/1995" , new Address("Wheeler's Road",10,"Belfast", "BT12 5EG", "Co.Antrim"),StudentMode.Fulltime, false);
Student student2 = new Student("Adam Smith", "12/11/1979" , new Address("Ivy Hill",67,"Belfast", "BT17 7BN", "Co.Antrim"),StudentMode.Parttime, true);
ArrayList<Person> uniPeople = new ArrayList<Person>();
uniPeople.add(student1);
uniPeople.add(student2);
printMenu(uniPeople);
}
public static void printAllDetails(ArrayList<Person> uniPeople) {
for (int i = 0; i < uniPeople.size(); i++) {
System.out.println(uniPeople.get(i).toString());
}
}
}
Output:
Student [ ID: 1002; Name: null; DOB: null; Study Mode: Fulltime; Number of Enrolled Modules: 0
Student [ ID: 1003; Name: null; DOB: null; Study Mode: Parttime; Number of Enrolled Modules: 0
Can anyone help me with this problem? Thanks
public Person(String name, String dob, Address address) {
super();
LAST_ID ++;
this.id = LAST_ID;
}
The constructor completely ignores its three arguments. It doesn't assign them to the corresponding fields, so these fields keep their default value: null.
You have to store the name value in the constructor. Your version did not use the name value.
public Person(String name, String dob, Address address) {
super();
this.name = name; // <== important line
this.dob = dob; // <== important line
this.address = address; // <== important line
LAST_ID ++;
this.id = LAST_ID;
}
Look at the constructor in person and in student, Should use the parameters in the method header.
super(name,dob,address)

Error while trying to print out arraylist

The error I am reviving is "void type is not allowed here " how would I fix this error in order to print out my array list.
import java.util.ArrayList;
public class Library
{
private ArrayList<Member>listOfMembers;
public Library()
{
listOfMembers = new ArrayList<Member>();
}
public void storeMember(Member Member)
{
listOfMembers.add(Member);
}
public int numberOfMembers()
{
return listOfMembers.size();
}
public void listMembers()
{
for (int item=0; item<listOfMembers.size(); item++ ) {
Member m = listOfMembers.get (item);
System.out.println(m.GetWholeName());
}
}
}
and here is my member class just in case you need it
class Member
{
// The fields.
private String firstname;
private String lastname;
private Integer number;
private Integer id;
/**
hehe
*/
public Member(String firstName, String lastName, Integer telNumber, Integer memberId)
{
firstname = firstName;
lastname = lastName;
number = telNumber;
id = memberId;
}
// Add the methods here ...
public void GetWholeName(){
System.out.println(firstname + (" ") + lastname);
}
}
I'm trying to print the first and last name of my member class by using an array list in my library class
You are trying to print out the result of m.GetWholeName() which returns void. Change GetWholeName to return a String instead, or simply call GetWholeName as it's already printing the name to standard out although that behavior doesn't quite match up to the behavior the name would imply.
public String GetWholeName() {
return firstname + " " + lastname;
}
In Member class change this:
System.out.println(firstname + (" ") + lastname);
to this:
return firstname + " " + lastname;

Java Inheritance of Classes

I am trying to figure out Inheritance and Arrays in Java and I am trying to get these classes to work together. I believe I have the Inheritance down, but I am still struggling with the array part.
There are three files: 1. Person.java -base class 2. Student.java -a derived class of Person.java 3. Family.java -not quite sure, I think it's its own base class
Person.java has two instance variables, String name and int age, and an assortment of constructors, toString, equals, and set/get methods
Student.java, again, a derived class of Person, by definition will have all the stuff contained within Person, as well as two more instance vars, String major, and double gpa. This class also have get/set methods for major and gpa, an equals method that compares one class student with another class student, and I believe it's called an overidden method of toString that returns name, age, major, and gpa all in one string.
Lastly, Family.java is where the main method resides. It creates an array of type Person, adds "Persons" to this array, then outputs them.
I am getting an error that says: "main" java.lang.ArrayIndexOutOfBoundsException: 8
I can not figure out why this program is not working properly and would appreciate any help to figure this out. Thank you.
Person.java Class
public class Person
{
private String name;
private int age;
public Person()
{
name = "John Smith";
age = 1;
}
public Person(String n, int a)
{
name = n;
age = a;
}
public String toString()
{
return ("Name: " + getName() + ", Age: " + age + " ");
}
public boolean equals(Person otherPerson)
{
return (getName().equals(otherPerson.getName()) && (age == otherPerson.age));
}
public String getName()
{
return name;
}
public void setName(String newName)
{
name = newName;
}
public int getAge()
{
return age;
}
public void setAge(int newAge)
{
age = newAge;
}
}
Student.java Class
public class Student extends Person
{
private String major;
private double gpa;
public Student()
{
super();
major = "Undecided";
gpa = 0.0;
}
public Student(String theName, int theAge, String theMajor, double theGpa)
{
super(theName, theAge);
setMajor(theMajor);
setGpa(theGpa);
}
public String toString()
{
return ("Name: " + getName() + ", Age: " + getAge() + ", Major: " + major + ", GPA: " + gpa);
}
public boolean equals(Student otherStudent)
{
return (major.equals(otherStudent.major) && (gpa == otherStudent.gpa));
}
public String getMajor()
{
return major;
}
public void setMajor(String newMajor)
{
major = newMajor;
}
public double getGpa()
{
return gpa;
}
public void setGpa(double newGpa)
{
gpa = newGpa;
}
}
Family.java Class
public class Family
{
private int famArray = 0;
private Person[] family;
public Family(int size_of_family)
{
famArray = size_of_family;
family = new Person[famArray];
}
public void addPerson(Person p)
{
boolean isPresent = false;
int i;
for(i = 0; i < family.length; i++)
{
if(family[i] != null && family[i].equals(p))
{
isPresent = true;
System.out.println(p.getName() +
" is already present in the family");
}
}
if(isPresent == false)
family[i] = p;
}
public void printOutFamily()
{
for(int i = 0; i < family.length; i++)
{
System.out.println(family[i].toString());
}
}
public static void main(String[] args)
{
Family f = new Family(8);
Person fred= new Person("Fred Flintstone", 50);
System.out.println("created " + fred);
f.addPerson(fred);
f.addPerson(fred);
Student fredStudent = new Student("Fred Flintstone", 50, "Math", 3.1);
System.out.println("created "+ fredStudent);
f.addPerson(fredStudent);
Person wilma = new Person("Wilma Flintstone", 48);
f.addPerson(wilma);
Student george= new Student("George", 21, "Politics", 3.1);
System.out.println("created " + george);
f.addPerson(george);
george.setName("Georgie");
f.addPerson(new Student("George", 21, "Politics", 3.1));
f.addPerson(new Student("John", 18, "Geology", 2.9));
f.addPerson(new Student("Jane", 21, "Music", 3.2));
f.addPerson(new Student("Tarzan", 22, "Gymnastics", 4.0));
f.addPerson(new Student("Jim", 21, "Physics", 2.5));
System.out.println("****** family listing: ");
f.printOutFamily();
}
}
Here's the problem, in Family#addPerson method:
if(isPresent == false)
family[i] = p;
You're adding the element in position i. If the element is not found, then i value will be family.length, thus giving you the exception.
Use int famArray field instead:
if(isPresent == false) {
family[famArray++] = p;
}
Or in an easier way for starters:
if(isPresent == false) {
family[famArray] = p;
famArray = famArray + 1;
}
As an addition to your current problem, you should first check if the famArray element is equals to family.length. If they're the same, then increase the array or do not allow more elements.
You state you have the same problem. This is because you're initializing famArray with the length of the array, noted in Family class constructor:
public Family(int size_of_family) {
famArray = size_of_family; //here
family = new Person[famArray];
}
Change the code to:
public Family(int size_of_family) {
famArray = 0;
family = new Person[size_of_family];
}
And you're done.
The problem is the line
family[i] = p;
This occurs after a for loop which increments i to be equal to the length of the array. I don't have any suggestions to fix it because I'm not sure what you are trying to do here.

Categories

Resources