Array of Student objects java - java

Just to give a run down of what I am trying to do, here is the HW my professor gave me:
Define a class Student which extends Person. It adds the attributes
Int Test1, test2, test3
Double average
String grade
It has methods computeaverage() and calculategrade(). The grades are based on the average, with above 90 an A, 80 to 90 a B, 70 to 80 a C etc. All other attributes have a set and a get.
Write an application that uses an array of type student of size 20. The program prompts the user for how many students are in the class and then allows them to enter the students and their test scores, then calculates their grades and prints out the list of students and their grades.
That being said...
On Thursday I saw a classmates code that he got from the teacher and he had something that I haven't seen before in my student class on line 37 (Student Constructor). Instead of having getters and setters he had code similar to what I have at line 37. But I have no idea what he did and the correct coding. So I was hoping someone here could tell me what I am doing wrong and how this code can get away without using getter and setter methods???
public class Person {
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
Scanner kbd = new Scanner(System.in);
Student newStudent = new Student();
int size;
System.out.println("Enter the amount of students:");
size = kbd.nextInt();
Student[] myStudent = new Student[size];
String firstName;
String lastName;
int test1, test2, test3;
Student s;
for (int i=0; i < size; i++)
{
System.out.println("Enter first name of student: " + i);
firstName = kbd.next();
System.out.println("Enter last name if student: " +i);
lastName = kbd.next();
System.out.println("Please Enter first test score: ");
// JOptionPane.showInputDialog("Please enter first test score:");
test1= kbd.nextInt();
System.out.println("Please enter second test score");
// JOptionPane.showInputDialog("Please enter second test score:");
test2= kbd.nextInt();
System.out.println("Please enter third test score");
// JOptionPane.showInputDialog("Please enter third test score:");
test3=kbd.nextInt();
// s = new Student (test1, test2, test3, firstName, lastName);
myStudent[i].setTest1(test1);
myStudent[i].setTest2(test2);
myStudent[i].setTest3(test3);
myStudent[i].setfName(fName);
myStudent[i].setlName(lname);
}
for (int i = 0; i < size; i++)
{
System.out.println(myStudent[i].getGrade());
}
}
}
public class Student extends Person{
int test1, test2, test3;
double average;
String grade, firstName, lastName;
public Student()
{
test1 = 0;
test2 = 0;
test3 = 0;
average = 0;
}
public Student(int test1, int test2, int test3, String firstName, String lastName)
{
this.test1 = test1;
this.test2 = test2;
this.test3 = test3;
this.setfirstName = firstName;
}
public double computeAverage()
{
average = (test1 + test2 + test3)/3;
return average;
}
public String calculateGrade()
{
average = computeAverage();
if (average < 60){
grade = "F";}
else if (average < 70){
grade = "D";}
else if (average < 80){
grade = "C";}
else if (average < 90){
grade = "B";}
else {
grade = "A";
}
return grade;
}
public int getTest1() {
return test1;
}
public void setTest1(int test1) {
this.test1 = test1;
}
public int getTest2() {
return test2;
}
public void setTest2(int test2) {
this.test2 = test2;
}
public int getTest3() {
return test3;
}
public void setTest3(int test3) {
this.test3 = test3;
}
public double getAverage() {
return average;
}
public void setAverage(double average) {
this.average = average;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}

Your Person class is wrong. It has no attributes or methods. There's no reason to extend it, because it brings nothing to the party.
You don't need getters or setters if the attribute is visible to the public, but that doesn't mean it's a good idea.
Try thinking more like this:
public class Person {
protected String firstName;
protected String lastName;
public Person(String f, String l) {
this.firstName = f;
this.lastName = l;
}
public String getFirstName() { return this.firstName; }
public String getLastName() { return this.lastName; }
}
public class Student extends Person {
public static final int MAX_GRADES = 3;
private int numGrades = 0;
private int maxGrades;
private int [] grades;
public Student(String f, String l) {
this(f, l, MAX_GRADES);
}
public Student(String f, String l, int maxGrades) {
super(f, l);
this.maxGrades = (maxGrades > 0) ? maxGrades : MAX_GRADES;
this.grades = new int[this.maxGrades];
}
public void addGrade(int grade) {
if (this.numGrades < this.maxGrades) {
this.grades[numGrades++] = grade;
}
}
public double getAverageGrade() {
double average = 0.0;
if (this.numGrades > 0) {
for (int i = 0; i < this.numGrades; ++i) {
average += grade[i];
}
average /= this.numGrades;
}
return average;
}
}

There are two constructors in Studentclass:
Constructor without parameters
Constructor with paramers (int,int,int,String,String)
This is called method/function overloading. You can declare many method with the same name, but the signature has to change. In other words, it has to have different parameters (so the compiler will know which version of the method to use).
So you have one constructor without parameters, that just set test1, test2, test3 and average to 0. And you have this constructor:
public Student(int test1, int test2, int test3, String firstName, String lastName)
{
this.test1 = test1;
this.test2 = test2;
this.test3 = test3;
...
}
that receives 4 parameters and assigns them to the respective fields.
Note that you should initialize average in the constructor too, as well as set firstName and lastName:
this.average = 0; // Or maybe 'this.average = computeAverage();'
this.firstName = firstName;
this.lastName = lastName;

Typically, you'll want to encapsulate your fields as much as possible. This means make these
int test1, test2, test3;
double average;
String grade, firstName, lastName;
things private. You'll then need getters and setters to access them from outside the class. That's a good thing. However, from inside the class, you can use them without getters or setters no problem.
Does this answer your question? I have no idea what is on line 37, as you didn't provide numbering. :)
Edit: In case you don't know, constructors can be overloaded. You have two different constructors, one with parameters, one without. You can choose which one you want to use to construct the class, you probably want to be using the second one.
If you have need for both constructors, one complete one and another one that uses default values, you might want to contemplate referencing the second constructor from inside the first, to avoid duplication of code. Like so:
public Student() {
this(0,0,0);
}
public Student(int test1, int test2, int test3, String firstName, String lastName) {
this.test1 = test1;
this.test2 = test2;
this.test3 = test3;
this.average = 0;
this.firstName = firstName;
this.lastName = lastName;
}

His instance variables (the variables declared at the beginning of Student) were public, which allowed him to access and change them directly without the use of setters and getters. Normally, these variables are private, requiring methods to access/change them.

Related

showing highest and lowest value of a series of objects in java

I have to find the highest scoring student and the lowest scoring student from the given user input.but i only get the highest scoring student and can't get the lowest scoring student from it.
public class Student{
public String name;
public String id;
public int score;
public static int n;
public Student(String initName,String initID,int initScore){
initName=name;
initID=id;
initScore=score;
}
public Student (){
}
public static void main(String[] args) {
System.out.println("Enter the number of students:");
Scanner s1=new Scanner(System.in);
Student.n=Integer.parseInt(s1.nextLine().trim());
System.out.println("Enter the student name,id and score.");
Scanner s2=new Scanner(System.in);
Student st1=new Student();
Student min=new Student(" "," ",100);
Student max=new Student(" "," ",0);
for(int i=0;i<Student.n;i++){
st1.name=s2.next();
st1.id=s2.next();
st1.score=s2.nextInt();
if(max.score<st1.score){
max.score=st1.score;
max.name=st1.name;
max.id=st1.id;
}
if(min.score>st1.score){
min.name=st1.name;
min.score=st1.score;
min.id=st1.id;
}
}
System.out.println("the highest scoring student: "+max.name);
System.out.println("the lowest scoring student: "+min.name);
}
}
initScore=score;
Please fix the above line in constructor.
Actually all the assignments are incorrect:
public Student(String initName,String initID,int initScore){
initName=name;
initID=id;
initScore=score;
}
It should be changed to
public Student(String initName, String initId, int initScore) {
name = initName;
id = initId;
score = initScore;
}
Even better
public Student(String name, String id, int score) {
this.name = name;
this.id = id;
this.score = score;
}
Since score is not assigned in the initial construction, it is assigned a default value of 0 and hence impacts the min computation. (as its already at min assuming the scores are positive)
It works for max computation as the scores obtained will be greater than or equal to 0 and will eventually update the score directly(assuming only positive scores are allowed).
I see plenty of problems in your code and it seems you don't really know how to code, which makes me wanna recommend going through some Java tutorial first.
Now to your code:
Student class implementation is just full of flaws, no encapsulation, mistakes in constructor, no idea what n is used for
public class Student {
private String name;
private String id;
private int score;
public Student(String initName, String initID, int initScore){
this.name = initName;
this.id = initID;
this.score = initScore;
}
// declare getters such as these two
public String getName() {
return this.name;
}
public int getScore() {
return this.score;
}
}
your main method has so many mistakes too: you have 2 Scanners, you don't initialize enough students and your iteration is plain wrong
public static void main(String[] args) {
Scanner s1 = new Scanner(System.in);
// get number of students
System.out.println("Enter the number of students:");
int numberOfStudents = s1.nextInt();
// initialize array of students
Student[] array = new Student[numberOfStudents];
for(int i = 0; i < numberOfStudents; i++) {
// get name of the student
System.out.println("Enter the student name:");
String name = s1.nextLine();
// get id of student
System.out.println("Enter the student id:");
String id = s1.nextLine();
// get score of student
System.out.println("Enter the student score:");
int score = s1.nextInt();
array[i] = new Student(name, id, score);
}
// now you have students input
// it's time to find your student
// set the lowest and highest student to first student
Student min = array[0];
Student max = array[0];
for(int i = 1; i < numberOfStudents; i++) {
if(min.getScore() > array[i]) {
min = array[i];
} else if(max.getScore() < array[i]) {
max = array[i];
}
}
System.out.println("the highest scoring student: "+max.getName());
System.out.println("the lowest scoring student: "+min.getName());
}
Carefully check the code again :
public Student(String initName,String initID,int initScore){
initName=name;
initID=id;
initScore=score;
}
Did you get it...? Buggy constructor.
The code should be
public Student(String initName,String initID,int initScore){
name = initName;
id = initID;
score = initScore;
}

JAVA Get & Set methods with calculations

new to Java and trying to set up get and set methods. Although one I need to do as calculation based off getSalary() multiplied by getMonths() to get a Year to Date total.
I haven't been able to find out if calculations are possible in get or set methods or I may just be such a newbie I have it in the wrong place.
public class Employee_v2
{
//Instance variables
private String first_name;
private String last_name;
private double salary;
private int months;
final double increase= 0.25;
private double year_to_date;
public Employee_v2()
{
//fill in the code to set default values to the instance variables
first_name="";
last_name="";
salary= 0.0;
months= 0;
}
//Constructor initializing instance variables with arguments
public Employee_v2(String f, String l, Double sal, int mo)
{
first_name = f;
last_name = l;
salary = sal;
months = mo;
}
//set arguments
public void setFirst(String f)
{
first_name = f;
}
public void setLast (String l)
{
last_name = l;
}
public void setSalary (double sal)
{
salary = sal;
}
public void setMonths (int mo)
{
months = mo;
}
public void setYtdSalary ()
{
double yearToDateSal;
yearToDateSal = getSalary() * getMonths();
}
//get arguments
public String getFirst()
{
return first_name;
}
public String getLast()
{
return last_name;
}
public double getSalary()
{
return salary;
}
public int getMonths()
{
return months;
}
public double getYtdSalary()
{
return yearToDateSal;
}
//DISPLAY
public void displayEmployee()
{
//display the name and salary of both Employee objects
System.out.println("Employee first name: " + getFirst());
System.out.println("Employee last name: " + getLast());
System.out.printf("Employee salary: $%.2f\n", getSalary());
//complete the code
System.out.println("-------------------------------");
//Determine the year to date salary for both employee
System.out.printf(getFirst() + "'s salary: $%.2f\n", getSalary());
// System.out.println(jas.getSalary());
System.out.printf("Year to date salary: $%.2f\n", getYtdSalary());
//set and display salary with increase
setSalary(getSalary()+ getSalary()*increase);
System.out.printf("New Salary: $%.2f\n", getSalary());
System.out.println();
System.out.println();
}//end method
}//end Class
Calculation are possible in getter and setter. I would do something like this:
public double getYtdSalary(){
double ytd = 0;
ytd = months * salary;
return ytd;
}
Like this you can calculate the year to date on the fly and is always accurate data. For example if you called the setMonths method you would also have to call the setYtdSalary before calling the getYtdSalary.
Also there is no need to call your getters in your class to access your private variables.
I would also suggest using Javadoc comment in your classes as they make it easier to understand what the methods do.
to answer your question: yes it is possible to do calculations
this is also needed in many places, as the main reason to use get and set methods is so you can check or manipulate the values before setting them in your class
I guess your Code will Crash on the printing of the year to date Salary, because the variable yearToDateSal is only valid in the Scope of your set Method.
public void setYtdSalary ()
{
double yearToDateSal;
yearToDateSal = getSalary() * getMonths();
}
you should declare your YearToDateSal variable in the beginning of the class, i.e. rigth after
final double increase= 0.25;
private double year_to_date;
private double yearToDateSal;
and in your setYtdSalary() remove the declaration of yearToDateSal;
this way you should be fine :)

Abstract Class Java Why is my program only printing 0.00?

Abstract Class Java Why is my program only printing 0.00?
public class TestEmployee
{
public static void main(String[] args)
{
Employee[] folks = new Employee[4];
folks[0] = new SalariedEmployee("Suzy",123,520000.00);
folks[1] = new WageEmployee("Fred",456,7.50,40);
folks[2] = new SalariedEmployee("Harry",234,45000.00);
folks[3] = new WageEmployee("Rita",345,7.76,38);
for(int i=0; i<folks.length; i++)
{
System.out.println(folks[i].getName()
+ " earns " + folks[i].getMonthlyPay() + " each month");
}
}
}
I added the missing classes needed to make
the program compile and run properly
abstract class Employee
{
private String name;
private int number;
public abstract double getMonthlyPay();
public Employee(String name, int number, double salary)
{
setName(name);
setNumber(number);
salary = getMonthlyPay();
}
public Employee(String name, int number, double salary, int hours)
{
setName(name);
setNumber(number);
salary = getMonthlyPay();
}
public String getName()
{
return this.name;
}
public int getNumber()
{
return this.number;
}
public String setName(String name)
{
this.name = name;
return this.name;
}
public int setNumber(int number)
{
this.number = number;
return this.number;
}
}
Please provide an explanation or insight as to why my program is only printing zeroes. I think this is where my problem lies
class SalariedEmployee extends Employee
{
private double yearSalary;
public SalariedEmployee(String name, int number, double salary)
{
super(name, number, salary);
yearSalary = getMonthlyPay();
}
public double getMonthlyPay()
{
double monthlyPay = yearSalary / 12;
return monthlyPay;
}
public String toString()
{
return(super.getName() + ", " + super.getNumber() + ", " + getMonthlyPay());
}
}
class WageEmployee extends Employee
{
private double wage;
private int hours;
public WageEmployee(String name, int number, double salary, int hours)
{
super(name, number, salary, hours);
}
public double getMonthlyPay()
{
double monthlyPay = wage * hours * 4;
return monthlyPay;
}
public String toString()
{
return(super.getName() + ", " + super.getNumber() + ", " + getMonthlyPay());
}
}
It’s not too difficult to track back to where the 0.00 comes from.
In you for loop in main you use folks[i].getMonthlyPay() to get the number to print. So let’s look into the implementations of getMonthlyPay(). There are two implementations, one in SalariedEmployee and one in WageEmployee.
In case of a SalariedEmployee the getMonthlyPay method uses the value of the field yearSalary. Which value is assigned to yearSalary? Have you editor or IDE find all the occurrences of yearSalary to see where a value is assigned to it. You will see that it happens nowhere. Since yearSalary is a field (more precisely, an instance variable), Java assigns 0.00 to it from the start (local varaibles inside a method are different). Since you never assign any other value, the value is still 0.00 when getMonthlyPay() divides it by 12 and returns the result. So this is where 0.00 comes from. Can you find a way to fix it?
In case of a WageEmployee — you should try the same exercise yourself, find out where the value comes from in WageEmployee.getMonthlyPay(). This time you will need to find out both where the value of wage and where the value of hours come from. Happy searching.

Finding the max value in an arraylist

In this program I wrote I have to print out the name of the customer who spent the most in the store. I need help searching the array list for the customer who spent the most.
package bestcustomer;
import java.util.*;
/**
*
* #author muf15
*/
public class BestCustomer {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
ArrayList<Double> sales = new ArrayList<Double>();
ArrayList<String> names = new ArrayList<String>();
double salesAmount;
System.out.println("Enter the sales for first customer: ");
salesAmount = in.nextDouble();
while(salesAmount !=0)
{
sales.add(salesAmount);
System.out.println("Enter customers name");
names.add(in.next());
System.out.println("Enter the next sales amount, 0 to exit: ");
salesAmount = in.nextDouble();
}
String bestCustomer = nameOfBestCustomer(sales, names);
}
public static String nameOfBestCustomer(ArrayList<Double> sales,
ArrayList<String> customers)
{
String name = "";
double maxSales;
return name;
}
}
You should wrap these two field in a class called probably Customer and then
Use Collections.max();
Collections.max(yourCollection, customComparator);
You should consider making Customer a class, but this would find the name with your current data structures:
public static String nameOfBestCustomer(ArrayList<Double> sales,
ArrayList<String> customers)
{
String name = "";
double maxSales = 0;
int index = -1;
for(int i = 0; i < sales.size(); i++) {
if(sales.get(i) > maxSales) {
index = i;
maxSales = sales.get(i);
}
}
if(index == -1) {
return null; //lists are empty
}
return customers.get(index);
}
I might be a bit late..
I think that if you create a Customer class with two fields, name and sale it would be better design as mentioned by other answers.
Then in BestCustomer you could loop through the list of customer, find the highest sales and return the name.
Something like this for BestCustomer
private ArrayList<Customer> customers = new ArrayList<Customer>();
public BestCustomer(){
Scanner in = new Scanner(System.in);
double salesAmount;
System.out.println("Enter the sales for first customer: ");
salesAmount = in.nextDouble();
while(salesAmount !=0)
{
System.out.println("Enter customers name");
String name = in.next();
customers.add(new Customer(name, salesAmount));
System.out.println("Enter the next sales amount, 0 to exit: ");
salesAmount = in.nextDouble();
}
String bestCustomer = nameOfBestCustomer();
System.out.print(bestCustomer);
}
private double highestSale(){
double highestSale = 0;
for(Customer c: customers)
if (c.getSales() > highestSale)
highestSale = c.getSales();
return highestSale;
}
public String nameOfBestCustomer(){
for (Customer c: customers)
if(c.matchSale(highestSale()))
return c.getName();
return null;
}
}
and this is the Customer
public class Customer {
private String name;
private double sales;
public Customer(String name, double salesAmount) {
this.name = name;
sales = salesAmount;
}
public boolean matchSale(double sales){
return this.sales == sales;
}
public double getSales(){
return sales;
}
public String getName(){
return name;
}
}
I am a beginner so I am pretty sure there is a more efficient way to do it. Also I am using two getters and as far as my understanding goes it is not the better design..
In Java8, if defined Customer like mikey said
customers.stream()
.max(Comparator.comparing(Customer::getSales))
.get()
.getName()

NullPointerException Error (Java)

I'm getting the NullPointerException when I use this method. Someone told me it is because student.getId() returns a null. I have tried to fix this, but I can't figure it out. Below is just a snippet of the code, just the method and the Student class.
edit: I added the part where the array was created.
Student[] students ;
public Student[] enterStudents(){
Scanner input = new Scanner(System.in);
System.out.println("Enter number of students");
int numOfStudents = input.nextInt();
Student[] students = new Student[numOfStudents];
int i;
for(i = 0; i <= numOfStudents - 1; i++){
System.out.println("Enter student's ID: ");
int id = input.nextInt();
System.out.println("Enter student's first name: ");
String first = input.next();
System.out.println("Enter student's last name: ");
String last = input.next();
System.out.println("Enter student's class: ");
String stuClass = input.next();
Student x = new Student(id,first,last,stuClass);
students[i] = x;
}
return students;
}
public void retrieveStuId(){
Scanner input = new Scanner(System.in);
System.out.println("Enter student id");
int searchID = input.nextInt();
int i;
for(i = 0; i < students.length; i++){
Student student = students[i];
int search = student.getId();
if (search == searchID) {
System.out.println(student.toString());
}
}
}
class Student{
private int studentID;
private String firstName;
private String lastName;
private String stuClass;
public Student(){
}
public Student(int id, String first, String last, String c ){
studentID = id;
firstName = first;
lastName = last;
stuClass = c;
}
public void setID (int id){
studentID = id;
}
public void setStuClass (String c){
stuClass = c;
}
public void setFirst(String first){
firstName = first;
}
public void setLast(String last){
lastName = last;
}
public String getFirst(){
return firstName;
}
public String getLast(){
return lastName;
}
public int getId(){
return studentID;
}
public String getStuClass(){
return stuClass;
}
public String toString(){
return "Student ID: " + studentID + " --- " + "Student Name: " + firstName + " " + lastName + " --- " + "Class:" + stuClass;
}
}
Thank for any help in advance.
Your students array has null values, which you try to dereference. The bug isn't in the code you posted, rather where the students array is created and filled.
Just check for null values, and print something like "student not found."
for(i = 0; i < students.length; i++){
Student student = students[i];
if ( student != null ) {
int search = student.getId();
if (search == searchID)
System.out.println(student.toString());
}
}
EDIT:
I checked your code, it works, I tested it by adding
public class StudentTest {
public static void main(String[] args) {
StudentTest s = new StudentTest();
}
public StudentTest() {
students = enterStudents();
retrieveStuId();
}
// your code here ...
Student[] students ;
// .... end
}
Check the place where you assign the array returned by enterStudents.
There are two problem with that code. First is related to shadowing as mentioned before.
Second, as long as Im concerned about this code there is problem with not assigned return type to variable. Basically I think you forgotten to assigned return from your method enterStudents to your variable. Hopefully it is clear for you :)
There is an undefined (null) Student in your students array.Check if it's not null then use getID method.
How did you create the student array? Is it initialized with a Student for every position?
To find out print the value of student after this line:
Student student = students[i];
with
System.out.println(student);
for example. Also check whether all the students in the array have been initialized with a
correct ID so getIt() returns a non-null value. (try printing the value after assigning to search).
You have two (that is TWO) declarations for something called students. One of them (the local variable) is being initialized, and the other (the instance variable) is not being initialized. The NullPointerException is being thrown when you try to use the one that is not initialized.
You shouldn't have two declarations.
Since this is homework, I'll leave it to you to figure out which declaration to delete ... and what to do about the other one.

Categories

Resources