I have been asked to create a class which simply prints "You have been registered".
In the second part, I am to create a test class. The test class should create two student instances (also called objects). Then to print their names and call the registered method of both of them. I keep getting errors saying 'the assignment to variable yearOfBirth has no effect' and in the test class 'The constructor String is undefined'.
Can you help with understanding the errors in my code.
public class Student{
//Attributes
private String name;
private String gender;
private int yearOfBirth;
//Constructors
public Student (String name, String gender, int yearOfBirth){
this.name = name;
this.gender = gender;
this.yearOfBirth = yearOfBirth; // Default age of new student
}
public Student (String name, String gender){
this.name = name;
this.gender = gender;
this.yearOfBirth = 0;
}
//Getters & Setters
public String getName() {
return name; }
public void setName (String name) {
this.name = name;
}
public String getGender () {
return gender;
}
public void setGender (String gender) {
this.gender = gender;
}
public int getYearOfBirth() {
return yearOfBirth;
}
public void setYearOfBirth() {
if(yearOfBirth >= 0 && yearOfBirth <= 100) {
this.yearOfBirth = yearOfBirth;
}else {
System.out.println("Age not valid");
}
}
// Other Methods
public void Registered() {
System.out.println(name + "You have been registered");
}
}
public class StudentTest {
public static void main(String[] args) {
Student student1 =new Student("Kevin Sanches", "male", "1972");
Student student2 = new Student("Cameron Young", "male", "1993");
student1.Registered();
student2.Registered();
System.out.println(student1);
System.out.println(student1);
}
}
There are two issues in your code:
The assignment to variable yearOfBirth has no effect. You are invoking a setter method on a property but you are not passing any value, hence the warning. You should provide a value as a parameter and set that to the corresponding object property.
The constructor problem is that the age parameter is of type int instead when you construct the objects you are passing the age as string.
Your constructor expects two strings and an integer as parameters. You are passing three strings.
Correct way:
Student student1 =new Student("Kevin Sanches", "male", 1972);
Student student2 = new Student("Cameron Young", "male", 1993);
Also, in your method setYearOfBirth you forgot to pass the yearOfBirth as parameter.
public void setYearOfBirth(int yearOfBirth) {
if(yearOfBirth >= 0 && yearOfBirth <= 100) {
this.yearOfBirth = yearOfBirth;
}else {
System.out.println("Age not valid");
}
}
You are trying to send 3 Strings which none of your constructors are ready to take. You have a constructor with 2 Strings and an int, so the correct way of creating the object would be,
Student student1 = new Student("Kevin Sanches", "male", 1972);
Without the double quotes 1972 would be an int.
You are assigning this.yearOfBirth to this.yearOfbirth in the setter. Even though code is just this.yearOfBirth = yearOfBirth; technically both are this.yearOfBirth variables.
This needs to change by accepting the value and assigning it like:
public void setYearOfBirth(int yearOfBirth) {
if(yearOfBirth >= 0 && yearOfBirth <= 100) {
this.yearOfBirth = yearOfBirth;
}else {
System.out.println("Age not valid");
}
}
You are trying to pass a String value to the constructor that accepts int for the yearOfBirth value, change it like:
Student student1 =new Student("Kevin Sanches", "male", 1972);
Student student2 = new Student("Cameron Young", "male", 1993);
Related
I have a program I am working with to help me practice my coding skills. The program has the following scenario: there is a classroom of 20 students, where the record is taken of the students' names, surnames, and age. Half of these students take part in the school's athletics. Here, record is kept of their races that they have done and the ones they've won.
In this program, I have three classes:
runStudents - class with main method
Students (String name, String surname, int age) - parental class
AthleticStudents (String name, String surname, int age, int races, int victories) - sub class
The user should be able to add another race (and win) to the object. As seen by the code provided, an Array is created to store the 20 Students objects. I have to be able to access a method to alter the object in the array, but this method is not in the parental class (the class the objects are created from.
public class Students
{
private String name;
private String surname;
private int age;
public Students()
{
}
public Students(String name, String surname, int age)
{
this.name = name;
this.surname = surname;
this.age = age;
}
public String getName()
{
return this.name;
}
public String getSurname()
{
return this.surname;
}
public double getAge()
{
return this.age;
}
public void setName(String name)
{
this.name = name;
}
public void setSurname(String surname)
{
this.surname = surname;
}
public void setAge(int age)
{
this.age = age;
}
public String toString()
{
return String.format("name\t\t: %s\nsurname\t\t: %s\nage\t\t: %s",
this.name, this.surname, this.age);
}
}
public class AthleticStudents extends Students
{
private int races;
private int victories;
public AthleticStudents()
{
}
public AthleticStudents(String name, String surname, int age, int
races, int victories)
{
super(name, surname, age);
this.races = races;
this.victories = victories;
}
public int getRaces()
{
return this.races;
}
public int getVictories()
{
return this.victories;
}
public void setRaces(int races)
{
this.races = races;
}
public void setVictories(int victories)
{
this.victories = victories;
}
public void anotherRace()
{
this.races = this.races + 1;
}
public void anotherWin()
{
this.victories = this.victories + 1;
}
public String toString()
{
return super.toString() + String.format("\nnumber of races\t:
%s\nnumber of wins\t: %s", this.races, this.victories);
}
}
public class runStudents
{
public static void main(String[]args)
{
Students[] myStudents = new Students[20];
myStudents[0] = new Students("John", "Richards", 15);
myStudents[1] = new AthleticStudents("Eva", "Grey", 14, 3, 1);
myStudents[2] = new Students("Lena", "Brie", 15);
for (int i = 0; i < 3; i++)
System.out.println(myStudents[i].toString() + "\n\n");
}
}
I want to be able to do the following:
AthleticStudents[1].anotherRace();
but cannot do so as the array object is derived from the parental class, and I declared the method in the sub class. How can I link the two?
I assume that you create an array of the parent class instances. Just cast the instance this way (you better check whether the element is the instance of a subclass):
if (AthleticStudents[1] instanceof AthleticStudents)
((AthleticStudents) AthleticStudents[1]).anotherRace();
I'm not sure if this is exactly what you're looking for but it worked well for me. Instead of trying to access AthleticStudents method anotherRace() like that, try this in your main method.
Students[] myStudents = new Students[20];
myStudents[0] = new Students("John", "Richards", 15);
myStudents[1] = new AthleticStudents("Eva", "Grey", 14, 3, 1);
myStudents[2] = new Students("Lena", "Brie", 15);
AthleticStudents addRace= (AthleticStudents)myStudents[1];
addRace.anotherRace(); //This will increment Eva's race count to 4
for (int i = 0; i < 3; i++)
System.out.println(myStudents[i].toString() + "\n\n");
All I did was cast the element into an object AthleticStudents named 'addRace'. By casting myStudents[1] to this new object you are able to access all of AthleticStudents methods.
I just saw the other answer posted which works just as well!
Hope this helps!
I’m not sure that i understand your question, because you are a bit inconsistent with your capitalization. runStudents is a class, while AthleticStudents is both a class and an array. But i’ll try.
IF i did understand your question, you have an array Student[] studentArray. Some Student objects in studentArray are AthleticStudents, others are not. You have a specific AthleticStudent eva which is in studentArray[] having let’s say index 1, and you want to add to her anotherRace(). Your call studentArray[1].anotherRace does not compile because the compiler treats that element as a Student and not as a AthleticStudent.
The trick is to cast the element to AthleticStudent. I omit the test of the element of being really an AthleticStudent; you will have to do that test in your code.
((AthleticStudent) studentArray[1]).anotherRace();
I want to add values to the objects with out looping because if there are 1000 of objects then I don't want to loop all of them.I want to add age randomly to the students based on the Name of the student.Is there are any way to add values
Here is the code
import java.util.*;
import java.io.*;
class Student{
Student(String Name){
this.Name=Name;
}
String Name;
int age;
}
public class HelloWorld{
public static void main(String []args){
String a []={"Ram","Krishna","Sam","Tom"};
ArrayList<Student> al = new ArrayList<Student>();
for(int i=0;i<a.length;i++){
Student c;
c=new Student(a[i]);
al.add(c);
}
for(Student obj:al){
if(obj.Name.equals("Krishna")){
obj.age=24;
}
System.out.println("Name = "+ obj.Name + " Age = " + obj.age);
}
}
}
First some minor points:
You should never use the fields directly but create getter and setters instead. The fields should be private. Variable names should start with a lower case letter by convention. So this would be the adjusted Student class:
public class Student {
private String name;
private int age;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
To store the Student objects you can use a map with names as keys and Student instances as values.
It is good practice to declare the variable only with the interface type Map and not with the concrete implementation HashMap. A hash map has O(1) complexity for searching by key. So you don't need a loop to iterate through all Student instances. (The HashMap.get() implementation doesn't use a loop internally.)
public static void main(String[] args) {
String a [] = {"Ram", "Krishna", "Sam", "Tom"};
// Keys: student names
Map<String, Student> al = new HashMap<String, Student>();
// Fill the Student's map
for(int i = 0; i < a.length; i++){
String name = a[i];
al.put(name, new Student(name));
}
// Manipulate one student by name. If there is no entry for that name we get null.
// So we better check for null before using it.
Student student = al.get("Krishna");
if(student != null) {
student.setAge(24);
}
// Output the all students
for(Student obj: al.values()){
System.out.println("Name = "+ obj.getName() + " Age = " + obj.getAge());
}
}
class AStudent {
private String name;
public int age;
public void setName(String inName) {
name = inName;
}
public String getName() {
return name;
}
}
public class TestStudent2 {
public static void main(String s[]) {
AStudent stud1 = new AStudent();
AStudent stud2 = new AStudent();
stud1.setName("Chan Tai Man");
stud1.age = 19;
stud2.setName("Ng Hing");
stud2.age = -23;
System.out.println("Student: name="+stud1.getName()+
", age=" + stud1.age);
System.out.println("Student: name="+stud2.getName()+
", age=" + stud2.age);
}
}
How can I enhance the class AStudent by adding data encapsulation to the age attribute. If the inputted age is invalid, I want to print an error message and set the age to 18.
First, modify age so that it isn't public. Then add accessor and mutator methods (in the mutator, check for an invalid value - and set it to 18). Something like,
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0) {
System.err.println("Invalid age. Defaulting to 18");
age = 18;
}
this.age = age;
}
Then you could use it with something like setName
stud1.setAge(19);
and
stud2.setAge(-23);
And you could make it easier to display by overriding toString in AStudent like
#Override
public String toString() {
return String.format("Student: name=%s, age=%d", name, age);
}
Then you can print yor AStudent instances like
System.out.println(stud1); // <-- implicitly calls stud1.toString()
System.out.println(stud2);
You are using encapsulation for the name attribute. You could do the same for age.
class AStudent {
// ...
private int age;
public void setAge(int age) {
this.age = age;
if (age < 1) {
this.age = age;
}
}
}
The above code changes the age attribute to private so that access is restricted to the getter and setter. So you will also have to add a getter method and change TestStudent2 to use the new getter and setter.
What makes an age invalid? The above code assumes any value less than 1 is invalid.
I am trying to solve an assignment in my Java class. I am stuck and need a little help.
I am trying to create a method in my Group class that will display the group name and the 4 students in the group. My code currently displays the group name and the memory location of my student inside my array.
public class Group {
/**-------Declaring attributes----*/
String groupName;
int newStudentCount;
/**----------------------------*/
/**--------Constructor------------*/
public Group(String givenGroupName) {
groupName = givenGroupName;
}
Student[] students = new Student[4];
/**----------------------------*/
/**--------Method------------*/
void addStudent(Student st) {
students[newStudentCount] = st;
++newStudentCount;
System.out.println("New student: " +st.getName());
}
public String getGroup() {
return "Group = " + groupName;
}
public Student getStudent(){
return students[0];
}
}
In my App class I have this:
public class App {
public static void main(String[] args) {
Group g1 = new Group("Pink Pony Princesses");
Student st1 = new Student("Joshua Mathews");
st1.getName();
g1.addStudent(st1);
Student st2 = new Student("Jame Brooks");
g1.addStudent(st2);
Student st3 = new Student("Mike Myers");
g1.addStudent(st3);
Student st4 = new Student("Christie Richie");
g1.addStudent(st4);
System.out.println(g1.getGroup()+ " " + g1.getStudent());
}
This is my Student class:
public class Student {
/**-------Declaring attributes----*/
String name;
String degree;
int age;
/**----------------------------*/
/**--------Constructor------------*/
Student(String givenName){
name = givenName;
}
Student(String givenName, String givenDegree, int givenAge) {
name = givenName;
degree = givenDegree;
age = givenAge;
}
/**--------- METHODS --------*/
//Array
public final String [] activities = {
"Working on Homework", "Playing a Game", "Taking a Nap"
};
String getInfo(){
return name + age + degree;
}
String getName() {
return name;
}
int getAge(){
return age;
}
String getDegree() {
return degree;
}
String whatsUp(){
Random rand = new Random();
int randomIndex = rand.nextInt(activities.length);
String returnActivity = activities[randomIndex];
return returnActivity;
}
I'm not sure how to call my array to display the 4 names, and not the memory location of them. Any help would be greatly appreciated.
I can deduce a couple of things from your question.
First, you are returning only the student at index 0 of the Student array held within your Group object. If you want to return all students your method signature should have a Student[] as the return type rather than a Student object.
If you follow the above prompt then you will have to iterate through the returned array printing each Student object.
Regardless of which implementation you choose the reason you print out a memory reference rather than a String object is that you have not overridden toString within your Student class.
Something like this will print out Student data when passed to a System.out call:
#Override
public String toString() {
return someStudentData;
}
You can go with what andrewdleach said by implementing toString(). OR
To print all student names your method should be something like:
public String getStudent(){
String studentNames = "";
for(Student stu: students){
studentNames+= stu.getName() + ",";
}
return studentNames;
}
I'm trying to find out how to make separate toString methods based on an overloaded constructor. Take the below code for example:
public class Employee {
private double salary;
private String name;
public Employee(String name) {
this.name = name;
}
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
}
Now, I would like to implement a toString method that is dependent on the object created and output the corresponding values.(i.e. one that outputs just name, the other that outputs name and salary) Do I need only one toString method and need to add an if-else statement?
Sorry if this is a silly question, I'm just learning the ropes of Java.
You can only have one toString(), but you can determine the object's "state" and put together the string accordingly. For instance, you can have a salary of -1 indicate that the first constructor was called. Therefore, your toString() would look like:
#Override
public String toString() {
if (salary < 0) {
...
} else {
...
}
}
Don't forget to set salary to -1 in the first constructor.
Well what you are doing here is just instantiating constructors, which has nothing to do with any methods. Constructors just help you initialize and sort of provide context to variables that you will be working with.
If as you said, printing or output-ing the salary and name, you would have to create methods like:
public String printName(){
return name;
}
public String printAll(){
return name + "" + String.valueOf(salary);
}
First, make your salary a negative double (hopefully no one pays to work)... then, default your name field to null. Finally, check for nulls (or negative) in toString(). So, something like this -
private double salary = -1;
private String name = null;
public Employee(String name) {
this.name = name;
}
public Employee(String name, double salary) { // <-- salary isn't an int.
this.name = name;
this.salary = salary;
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (name != null) {
sb.append(name);
if (salary > 0) { // = only if both are valid.
sb.append(" = ");
}
}
if (salary > 0) {
sb.append(salary);
}
return sb.toString();
}