How to use an object without knowing the objects' name - java

I'm not too sure how to word this so it makes sense, but I'll try my best.
Say I have 2 classes. My main class, and a Person class.
My main class will create some Objects from the Person class like this
public class Example {
static Person bob = new Person(23);//Age
static Person fred = new Person(34);
static Person John = new Person(28);
//..and so on
public static void main(String args[]){
..
}
}
and in my Person class..
public class Person{
private int age;
public Person(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
}
Now, if I wanted the age of fred, I'd just call Fred.getAge();.
But, in my program, I don't know what person I'm getting the age of. It randomly selects one, and I need to get the name without directly calling the object. For example, I would have something like this in my Person class:
public static Object getPerson(){
//Some code to get a random integer value and store it it Var
switch(Var){
case 1:
return bob;
case 2:
return fred;
case 3:
return john;
}
}
What I would expect this to do is return an Object that I could then use like this:
public static void main(String args[]){
System.out.println(Person.getPerson().getAge());
}
What I thought that would have done was first call getPerson() which randomly returns either bob, fred, or john, and then it would call getAge(). So if getPerson() returned fred then it would be the same as doing fred.getAge();
Now, this doesnt work, and this was the only way I thought of that made sense to me.
How do I do this so it actually does what I want?
I'm very new to Java, and OOP, and this is my first time really working with different Objects. So I'm sorry if I'm using the wrong terms and explaining things weirdly.

Change
public static Object getPerson(){
to
public static Person getPerson(){
You can't call getAge on an Object, because the Object type does not have getAge() defined.

Why not put the name as a property of the Person class?
class Person {
// ... your existing code for age...
private String name;
String getName() { return name; }
// add name to constructor...
public Person(String name, int age) {
// set them up here...
}
}
The way I see it, is that name is for you as a human, but variables john are irrelivant to the program and computer.... you can even use p1 = Person("Joe", 42);
To get a person by age, you can use a Map with age as key, and person as value.

It could be the case that this is a misunderstanding, but how I'm interpreting the issue is as follows:
You need a (better) place to store all of your Person objects instead of having them as static variables.
You need a way to randomly select from wherever you're storing those objects.
Let's address the main issue first. You're creating these as static variables when they probably shouldn't be; they should just be created as entries into an array.
The way to do this is through this declaration:
Person[] people = new Person[] {new Person(23), new Person(34), new Person(28)};
The main issue now is that you have no way to refer to which person's age belongs to whom since you haven't attached a name field to any of these instances. You could do that easily:
public class Person {
private String name;
private String age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters for name and age
}
...then you can instantiate your Person with two values.
new Person("Bob", 23);
Now that we've addressed one concern (which was where to store the people in the first place), now we need a way to randomly access them.
For that, we can use Random#nextInt().
Random rand = new Random();
System.out.println("Person's age - " + people[rand.nextInt(people.length)]);
This will randomly pull a Person out of the array and print their age.

If you want to get a random person within the person class you could store a reference to each person created, and then select randomly from that list
public class Person {
// A List of every Person Created.
private static final List<Person> allPeople = new ArrayList<People>();
// A source of random numbers
private static final Random rand = new Random();
...
public Person(int age) {
...
// Every time we create a new Person, store a reference to that person.
addPerson(this);
}
// synchronized as ArrayLists are not thread safe.
private static synchronized addPerson(Person person) {
allPeople.add(person);
}
...
public static Person getRandomPerson() {
// Get a random number between zero and the size of the list.
int random = rand.nextInt(allPeople.size() -1);
return allPeople.get(random);
}
Now this code is not what I would do in a production environment but it the question sounds like an exercise. A better way would be to store the people created in a List in your Example class. But trying to answer the question as you asked it.

Related

Create ArrayList from array using temporary object

I know there are standard way by add a constructors to the class. But for classes with object superclass (has no-argument constructor) I tend to find using a temporary object simpler. Is there any down side for such an act.
import java.util.ArrayList;
public class Main {
public static void main(String[] args){
// data available in two separated arrays
String[] dName = {"Sam","Ben","Joye","Sarah","Tim","Lucy","Jack"} ;
int[] dAge= {10,52,53,15,12,60,21};
// Array list to put the data in
ArrayList<Person> personList =new ArrayList<Person>(7);
for (int i=0;i<dName.length;i++){
Person tempPerson = new Person();
tempPerson.name= dName[i];
tempPerson.age= dAge[i];
personList.add(new Person());
personList.set(i,tempPerson);
tempPerson=null; //removes the reference
}
for (int j=0 ; j<personList.size();j++){
System.out.println(personList.get(j).name+" age is "+personList.get(j).age );
}
}
}
class Person{
String name;
int age;
}
the output
Sam age is 10
Ben age is 52
Joye age is 53
Sarah age is 15
Tim age is 12
Lucy age is 60
Jack age is 21
You should avoid statements that do nothing - an optimization would be to do
for (int i=0;i<dName.length;i++){
Person tempPerson = new Person();
tempPerson.name= dName[i];
tempPerson.age= dAge[i];
personList.add(tempPerson);
}
No need to first add the person to later replace it
No need to null the reference - the list will keep the reference to the temp object in any case.
Instead of setting values directly you could use setters (setName() instead of .name = )
If you'd use setters, you could implement a Builder pattern:
like this:
public Person setName(String aName) {
name = aName;
return this;
}
Resulting in something like
personList.add(new Person().setName(dName[i]).setAge(dAge[i]));
Then again - the two value constructor will probably be the easiest of all - and it don't matter that the super class doesn't have a constructor:
public Person(String aName, int aAge) {
name = aName;
age = aAge;
}
//You can have more than one constructor
public Person() {
}
and then
personList.add(new Person(dName[i], sAge[i]));
You should use a constructor for Person. Then you have just one call in your for-loop:
personList.add(new Person(dName[i], dAge[i])
Also, in your implementation, you are doing the necessary work twice, because you call personList.add(new Person()) and then you call personList.set(i, temPerson). If you don't want a constructor in your Person-class, a call of personList.add(tempPerson) for example would be enough.
Not really,
you could maybe make use of java8 streams, but why make your life harder, it wouldnt add anything new

Change the name of a class object Java, use class as array

Here are my instructions:
Class Person
has instance data members (all private) String fullName, char gender, int age.
has a public static int variable named numFriends with an initial value of zero.
has a constructor that will be used to make a Person object and assign values to its data members, and increment numFriends.
has getters and setters for all three instance data members.
has a toString() method that returns a string displaying the state of a Person instance.
Class TestPerson
This class needs a main method and two more methods. In main, create three Person instances and display their status. Then call the void changeName method (see below) to change the name of one of the Person objects. Next, create an array of Person objects that holds the three instances created earlier. Then, call the agePersons method with this array and an integer as arguments. The agePersons method is described below. It returns an array with all Person objects aged by the value of the yrs argument. Use a loop to process and display the status of the elements in the array returned by agePersons. Finally, display the value of the static numFriends attribute.
public static void changeName(Person p) {
}
this method should be used to change the name of the Person passed to it as an argument. See sample output.
public static Person[ ] agePersons(Person[ ] ara, int yrs) {
}
this method takes a Person array and an integer (for years) as arguments, and adds that many years to the age of every Person in the array. The modified array is then returned.
SAMPLE OUTPUT
Three people at first
Person fullName=Otto Mattik, gender=M, age=22
Person fullName=Anna Bollick, gender=F, age=19
Person fullName=Dick Tator, gender=M, age=33
Three persons after 5 years
Person fullName=Otto Mattik, gender=M, age=27
Person fullName=Anna Bollick-Mattik, gender=F, age=24
Person fullName=Dick Tator, gender=M, age=38
We created 3 Person objects.
So far here is my code:
class Person {
private String fullName;
private char gender;
private int age;
public static int numFriends = 0;
public void setName(String nm) {
fullName = nm;
}
public void setAge(int a) {
age = a;
}
public void setGender(char g) {
gender = g;
}
public String toString() {
return (fullName + " gender is " + gender + " age is " + age );
}
}
And here is the second code file:
public class PersonTest {
public static void changeName(Person p, String nm) {
p.setName(nm);
}
public static Person[ ] agePersons(Person[ ] ara, int yrs) {
}
public static void main(String[] args) {
System.out.println("Three People At First:");
Person p1 = new Person(); // create Person
p1.setAge(22);
p1.setName("Otto Mattik");
p1.setGender('M');
Person p2 = new Person(); // create Person
p2.setAge(19);
p2.setName("Anna Bollick");
p2.setGender('F');
Person p3 = new Person(); // create Person
p3.setAge(38);
p3.setName("Dick Tator");
p3.setGender('M');
changeName(p2, "Anna Bollik-Mattik");
System.out.println(p1.toString());
System.out.println(p2.toString());
System.out.println(p3.toString());
}
}
And this is my output:
Three People At First:
Otto Mattik gender is M age is 22
Anna Bollick-Mattik gender is F age is 19
Dick Tator gender is M age is 38
I'm having a tough time figuring out how to set up my array with the objects that were already created and getting the age to increase across the board.
You're going to have to iterate through all the Persons in the array
public static Person[ ] agePersons(Person[ ] ara, int yrs) {
Person[] newArray = new Person[ara.length];
for (int i = 0; i < ara.length; i++){
newArray[i] = ara[i];
newArray[i].setAge(newArray[i].getAge() + yrs);
}
return newArray;
}

Link ArrayLists and save data on file

I am working on a Java app for a school project where we have to enter user information: Name, Student ID and their points. How can I store all the data for each user on an ArrayList (or an Array or really whatever type) so I can keep track of all the data.
Example:
John Doe - 401712 - 20 points
Jack Young - 664611 - 30 points
The I want to be able to call methods like setPoints to change the point values for whatever the student selected is.
Here's the problem: How can I link the ArrayList together. If I have three ArrayLists, how does Java know what name, student id and points are associated together?
All the ArrayLists are stored in a class called Data.
Data data = new Data();
Also, all the ArrayLists in the Data class should be outputted to a file which will be loaded next time the app is opened.
I will try to answer any questions.
You need to define a class which contain 3 data fields as follows
Name
Student ID
their points
But not to forget, the class has to have other necessary elements of a class like:
Constructor
Overloaded Constructors if they are necessary
Accessors
Mutators
Note: For accessing each part of an object in your arrayList, you can use accessors. For manipulating each part of an object in your arrayList, you can use mustators.
After having such a class, you can define a arrayList that contain elements with type of class you have already define
Like:
List<Your Type of class > students = new ArrayList<Your Type of class>;
After Java 7, you can do
List<Your Type of class > students = new ArrayList<>;
which is diamond inference.
If you are looking for a specific id number in your arrayList, you can do something like:
public boolean findIdNumber(int idNumber){
for(int i=0; i< students.size; i++)
if(students.get(i).getID() == idNumber)
return true;
else
return false;
}
Warning:
what I have done are suggestions for you to be able to look for what you want smoother. You need to do necessary changes in order to comply what you were
asked to do
You need to create a class named Student, and then declare an array/ArrayList of the Student type. Your Student class must have a constructor that sets the fields of an instance of the Student class (the created instance is now called an object).
So first create a Student class in the same package in which your other class is (the class in which your main method is):
public class Student {
private String firstName;
private String lastName;
private String studentId;
private int points;
public Student(String firstName, String lastName, String studentId, int points) {
this.firstName = firstName;
this.lastName = lastName;
this.studentId = studentId;
this.points = points;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
}
Then in your main method or wherever you like, create a Hashmap to hold your Student objects. A map/hashmap is a collection just like an ArrayList to hold a set of objects. In your use case, it is better to use a hashmap because finding/retrieving a specific student object is much faster and easier when you use a hashmap.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
// a map is a "key-value" store which helps you search items quickly
// (by only one lookup)
// here you consider a unique value of each object as its 'key' in the map,
// and you store the whole object as the value for that key.
// that is why we defined Student as the second type in the following
// HashMap, it is the type of the "value" we are going to store
// in each entry of this map.
Map<String, Student> students = new HashMap<String, Student>();
Student john = new Student("John", "Doe", "401712", 20);
Student jack = new Student("Jack", "Young", "664611", 30);
students.put("401712", john);
students.put("664611", jack);
Student johnRetrieved = students.get("401712");
// each hashmap has a get() method that retrieves the object with this
// specific "key".
// The following line retrieves the student object with the key "664611".
Student jackRetrieved = students.get("664611");
// set/overwrite the points "field" of this specific student "object" to 40
johnRetrieved.setPoints(40);
int johnsPoints = johnRetrieved.getPoints();
// the value of johnsPoints "local variable" should now be 40
}
}
The classical object-oriented approach would be to create a Student class including name, ID and points and storing list of Student objects in a single ArrayList.
class Student{
private String id;
private String name;
private int points;
public Student(String id, String, name, int points){
this.id = id;
this.name = name;
this.points = points;
}
}
..
ArrayList<Student> students = new ArrayList<Student>();
students.add(new Student(1, 'John Doe', 1000));
String id = students.get(0).id;

Where to add members of java classes

Implement a class Student. For the purpose of this exercise, a student has a name and a total quiz score. Supply an appropriate constructor and methods getName(), addQuiz(int score), getTotalScore(), and getAverageScore(). To compute the latter, you also need to store the number of quizzes that the student took.
...
I am having an especially hard time with the scores and name. Do I add the scores to both the Student.java and the StudentTester.java files or only the tester? I cannot figure this out.
Here is my code:
/** A student has taken a number of quizzes and has an average score
based on the quizzes that were taken.
*/
public class Student
{
private String name;
private double totalscore;
private int numquiz;
}
// Constructs a student object with the name "MccStudent" and with zero total of quiz scores
public Student(String "mccStudent")
{
this.name = studentname;
numquiz = 0;
totalscore = 0;
}
public String getName()
{
return name;
}
// Adds the number of quizzes taken
public void addQuiz(double quizscore)
{
totalscore+=quizscore;
numquiz++;
}
// Returns the total quiz score
public double getTotalScore ()
{
return totalscore;
}
// Returns the avaerage grade
public double getAverageScore ()
{
return totalscore/numquiz;
}
}​
/** Create a class to test the Student class.
*/
public class StudentTester
{
/**
Tests the methods of the Student class.
*/
public static void main(String[] args)
{
// Create an object
Student mccStudent = new Student();
mccStudent.addQuiz(100);
mccStudent.addQuiz(80);
mccStudent.addQuiz(95);
mccStudent.addQuiz(97);
System.out.println(mccStudent.getName());
System.out.println(mccStudent.getTotalScore());
// Display average quiz score
System.out.println(mccStudent.getAverage.Score());
}
}​
First of all try to understand what Constructor is. Here is oracle documentation with nice examples: Constructor. Ill write simple example for you. Student is new Object that has String name attribute.
public class Student {
public String name; //name of student
public Student(String name) {//Constructor for student, receiving name when u create new object Student
this.name = name; //set received name to this public String name
}
/**
* When u call this method you will get inputed name from constructor
* so if u call Student stud = new Student("John");
* new Student("John") is constructor!
* with stud.getName(); you will get "John".
* This is called getter.
* #return name of student
*/
public String getName() {
return name;
}
}
There are some major issues here, for one the first brace is closed after declaring your instance variables, so the rest of the code for Student is out of scope. Remove the first close brace, and that should help that.
Another issue is the way you are using your constructor (the part that says public Student(String "mccstudents")). You need to providing a variable name there, and then whenever you make a new object, you pass in a string, and that will take the place of the variable name.
Not to sound like one of your teaches, you really shouldn't leave this to last minute To jump the gun on any number of people who will write a reply for this, this site is designed to help specific issues, not analyse the whole program.
Are there particular issues and concepts that you are not understanding that I can help with?
You add the fields to the class itself (Student.java).
Only code that performs tests should appear in the test class (StudentTester.java).

Java: Adding Fields to Sub-Class Constructors?

For example, say I have the 3 classes Person, Student and Teacher. The Person class would have general details about the people (name, age, email etc) which both the Student and Teacher class will extend. On top of this though, these classes will also have their own unique fields (e.g. wage & courseTaught (or "tought"?) for Teacher and schoolYear & classNumber for Student). If I just show the initial code I've got, maybe someone could point me in the right direction. Because Person doesn't have a courseTaught field, currently I'm just getting the output "Josh (null)" rather than "Josh (Computer Science)". Any help would be appreciated :)
public class Main {
public static void main(String args[]){
Teacher t = new Teacher("Josh", "Computer Science");
System.out.println(t.name + " (" + t.courseTaught + ")");
}
}
public class Person {
String name;
public Person(String pName){
name = pName;
}
}
public class Teacher extends Person{
String courseTaught;
public Teacher(String tName, String tCourseTaught){
super(tName);
}
}
The problem is simpler than you think. You're on the right track but you forgot to assign courseTaught in your Teacher constructor. The initial value of courseTaught is null and it stays that way because you never assign it to anything.
You'd want something like this:
public Teacher(String tName, String tCourseTaught){
super(tName); // <- takes care of Persons's field
courseTaught = tCourseTaught; // <- but don't forget to set the new field, too.
}
And yes, "taught" is the correct word.
As an aside, since you did tag your question "oop", you may want to check out this article on encapsulation for some information about the use of "getters" and "setters".

Categories

Resources