I need to have a class with two constructors, one with and one without arguments. The one without is supposed to call the other with Randomized arguments, so not default ones.
Here is some sample code:
public Human(int ageIn, String nameIn){
this.name = nameIn;
this.age = ageIn;
}
public Human(){
String[] names = {"Peter", "Olof", "Alva", "Sanna", "Carl", "Illona"};
double random = Math.random();
int nameIndex = (int)(names.length*random+0.5);
String name = names[nameIndex];
random = Math.random();
int age = (int)(100*random+0.5);
this(age, name);
}
The thing that makes this hard is that this() has to be in the beginning of a constructor, but I have to define and figure out name and age before I can call the first constructor with them.
Is there any way around this?
You can make static methods which make these random values. Then on line 1 of your constructor you can call:
public Human(){
this(getRandomAge(), getRandomName());
}
Alternatively you could create a factory method to create a 'random' Human:
public class MyProgram {
public static void main(String[] args) {
Human someRandomStranger = Human.createRandomHuman();
//...
}
}
public class Human {
public Human(int ageIn, String nameIn){
this.name = nameIn;
this.age = ageIn;
}
// ...
public static Human createRandomHuman(){
String[] names = {"Peter", "Olof", "Alva", "Sanna", "Carl", "Illona"};
double random = Math.random();
int nameIndex = (int)(names.length*random+0.5);
String name = names[nameIndex];
random = Math.random();
int age = (int)(100*random+0.5);
return new Human(age, name);
}
}
This would keep your constructors clear from stuff that shouldn't be there in the first place.
A default constructor that randomly assigns values to it's fields might be accidentially called in your code and create unwanted results.
A properly named factory method on the other hand would help prevent such mistakes and clearly communicate your intention.
How about something like this?
public class Human {
public Human() {
this(null, -1);
}
public Human(String name, int age) {
if(name == null) {
name = //your random name generation code
}
if(age == -1) {
age = //your random age generation code
}
this.name = name;
this.age = age;
}
}
Don't mix concerns. A Human should not care about choosing a random name based on a predefined set of names nor compute a random age !
I would rather delete the no-arg constructor (except if you have one defined value for a name and for an age, but it seems that it's not your case) and extract this logic outside of Human, typically in a HumanFactory.
Related
I created a constructor with methods to create "student" objects and part of it is supposed to assign a student number to each student and increase that number by one with each student created.. mine aren't increasing.
this is the constructor
String firstNameInput;
public Student(String fName, String lName, String maj, double gpa)
{
this.firstName = fName;
this.lastName = lName;
this.major = maj;
this.gpa = gpa;
sNumber = 1234567;
}
Here's the method that returns the student number
public int getsNumber() {
return sNumber + count++;
}
here's my toString method
public String toString()
{
return sNumber + " " + firstName + " " + lastName + " " + major + " " + gpa;
}
and here's where a student gets added.
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
Student s1 = new Student("Terra", "Ramey", "EE", 3.4);
list.add(s1);
Let me know if I need to include all of my code to figure out where the problem is, but I think it's with one of these
count++ is located inside the method getsNumber(). There are two problems with that:
The method is never called (at least, not in the code you've shown), hence you don't see the number increase.
You would presumably call this method whenever you want to know the student number of a student - so every time you try to figure that out, the number will increase.
Since this looks like homework, I won't tell you where to place count++, but here's a strong hint: which method is run each time a new student is created (and never otherwise)?
Also, see the other posters' advice about static (you haven't shown the declaration of count, so we can't tell if you're already using it). However, please make sure that you understand what static does and how a static variable is different from a nonstatic one (a lot of new programmers end up throwing static around, thinking it's magic and hoping it will solve their problems).
Add a static variable to the class. Something like the following :
private static int count = 0;
private int studentNumber;
Then in the constructor add the following :
public Student(String fName, String lName, String maj, double gpa)
{
this.firstName = fName;
this.lastName = lName;
this.major = maj;
this.gpa = gpa;
sNumber = 1234567;
count = count +1; // to keep the count
this.getStudentNumber = count;
}
Also add the following method to the Student class:
public int getStudentNumber(){
return this.studentNumber;
}
Then in your main you can access the count by :
Student student = new Student(//parameters);
System.out.println(Student.count);
System.out.println(student.getStudentNumber());
If you are allowed to use static fields to store the current count, I think you'll find adding a private static int currentCount to the class and then assigning the field sNumber = count++; might work for you.
Make sure that you use an AtomicInteger instead of just an int. That way, your constructor can be called by several threads simultaneously safely.
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.
I've been playing around with arrays for some time and this problem has been troubling me.
I created a user defined object and declared it in an array like this: `Property regesteredAssets[] = new Property[200];
And here's my constructor: `
public Property(String newPropertyName,String newPropertyAddress,String newPropertyType, String newPropertyDescription)
{
propertyName[arraySequence] = newPropertyName;
propertyFullAddress[arraySequence] = newPropertyAddress;
propertyType[arraySequence] = newPropertyType;
propertyDescription[arraySequence] = newPropertyDescription;
arraySequence++;
}
I want to initialize each array regesteredAsssets[] according to my desire. How can I do it?
Do I have to use arrays in my attributes in the Property class too?
You do not need your attributes to be arrays, unless a particular asset has multiple of something. In this case, I don't think it does. You can greatly simplify your code as follows:
public class Property {
private String name, address, type, description;
public Property(String name, String address, String type, String description) {
this.name = name;
this.address = address;
this.type = type;
this.description = description;
}
public static void main(String[] args) {
Property[] registeredAssets = new Property[200];
registeredAssets[0] = new Property("Joe Bloggs", "555 Fake St.", "IMPORTANT", "Lorem Ipsum Dolor");
// etc.
}
}
If you have an array of type Property, you can set each of the elements up using the following code:
regesteredAssets[0] = new Property( enterYourParametersHere );
I assume the fields in your Property constructor are single fields, and therefore you do not need to set them using the array notation field[index] = value, and indeed, if the Property class is of the consistency I think it is, then this will produce a compilation error.
If you wanted to set up multiple entries in your array, you could perform the initialisation step inside a loop, providing a loop index to the index of the array as below:
for( int i = 0; i < 10; i++ )
{
regesteredAssets[i] = new Property( enterYourParametersHere );
}
I hope this helps...
I'm currently writing a program that should read through a text file, create an array of different types of employees (each have their own subclass), then print out the information in a different format. I think I've got most of it working, but whenever I try to actually create the objects (at least I think that's what it is?), I'm getting a "Constructor is undefined" error. This is happening on all 7 of these objects. I will simply post one here (along with its subclass) so that you guys aren't overloaded with information, and hopefully I can figure out the rest from that.
Thanks for any help you can provide!
Driver class where I'm reading and creating objects (did not include the rest of the code following this)
Error occurs at the "Emp[0]" line
import java.io.File;
import java.util.Scanner;
public class PayrollSystemTest2 {
/**
* #param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Scanner input;
input = new Scanner(new File("EmployeePayrollInfo.txt"));
Employee[] Emp = new Employee[20];
while(input.hasNext())
{
String ID = input.nextLine();
if (ID.charAt(0) == 'S')
{
String first = input.nextLine();
String last = input.nextLine();
String ssn = input.nextLine();
Date DayOfBirth = new Date(input.nextInt(),input.nextInt(),input.nextInt());
double salary = input.nextDouble();
Emp[0] = new SalariedEmployee(first, last, ssn, DayOfBirth, ID);
}
SalariedEmployee subclass
public class SalariedEmployee extends Employee
{
private double weeklySalary;
// four-argument constructor
public SalariedEmployee( String first, String last, String ssn, Date DayOfBirth, String ID,
double salary )
{
super( first, last, ssn, DayOfBirth, ID); // pass to Employee constructor
setWeeklySalary( salary ); // validate and store salary
} // end four-argument SalariedEmployee constructor
// set salary
public void setWeeklySalary( double salary )
{
double baseSalary;
if ( salary >= 0.0 )
baseSalary = salary;
else
throw new IllegalArgumentException(
"Weekly salary must be >= 0.0" );
} // end method setWeeklySalary
// return salary
public double getWeeklySalary()
{
return weeklySalary;
} // end method getWeeklySalary
// calculate earnings; override abstract method earnings in Employee
#Override
public double earnings()
{
return getWeeklySalary();
} // end method earnings
// return String representation of SalariedEmployee object
#Override
public String toString()
{
return String.format( "salaried employee: %s\n%s: $%,.2f",
super.toString(), "weekly salary", getWeeklySalary() );
} // end method toString
} // end class SalariedEmployee
Again, thanks for any help you can provide.
Well yes - look at your constructor, including the clearly-inaccurate comment:
// four-argument constructor
public SalariedEmployee(String first, String last, String ssn, Date DayOfBirth,
String ID, double salary)
Note how there are 6 parameters. Now here's how you're trying to call it:
Emp[0] = new SalariedEmployee(first, last, ssn, DayOfBirth, ID);
You're passing in 5 arguments. What happened to the salary?
As side notes:
Java variables are conventionally camelCased - so dayOfBirth and id rather than DayOfBirth and ID
Using double for financial values such as a salary is a bad idea. Use BigDecimal or keep an integer number of cents. (That's assuming you even need it down to the cent...)
This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 7 years ago.
I created a program with a new class called Student that sets and gets different variables such as name, GPA, if they are enrolled and when they are enrolled (this is a String, it is intended to be). The problem is that when I try to store the information into an array and/or array list and print it I get the hash code printed instead of the information. The program is not entirely complete, but I am trying to address the hash code issue first. If you could assist I would much appreciate. Thank you in advance!
Student st = new Student();
System.out.println(st.getName());
Student1();
Student st1 = new Student("John");
}
public static void Student1() {
System.out.println("Enter the data for student 1 :");
Student st = new Student();
Scanner keyboard = new Scanner(System.in);
String name = keyboard.next();
double GPA = keyboard.nextDouble();
boolean enrolled = keyboard.nextBoolean();
String date = keyboard.next();
for (int i =0; i<5; i++){
Student newStudent = new Student();
newStudent.setName(name);
newStudent.setGPA(GPA);
newStudent.setEnrolled(enrolled);
newStudent.setDate(date);
ArrayList <Student> strList = new ArrayList<Student>();
Student student[] = new Student[5];
newStudent.getName();
student[i] = newStudent;
strList.add(newStudent);
System.out.println(student[i]);
}
Student Class
public class Student {
private String name;
private double gpa;
private boolean enrolled;
private String enrollDate;
public Student() {
this.name = "";
this.gpa = 0.0;
this.enrolled = false;
this.enrollDate = "none";
}
public Student(String name1) {
this.name = name1;
this.gpa = 0.0;
this.enrolled = false;
this.enrollDate = "none";
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setGPA(double gpa) {
this.gpa = gpa;
}
public double getGPA() {
return this.gpa;
}
public void setEnrolled(boolean enrolled) {
this.enrolled = enrolled;
}
public boolean getEnrolled() {
return this.enrolled;
}
public void setDate(String date) {
}
}
This is because you are putting a student object into the array:
Student student[] = new Student[5];
newStudent.getName();
student[i] = newStudent;
strList.add(newStudent);
System.out.println(student[i]);
Here when you are printing, you are not printing the students name, but rather the object itself. Whenever you do a System.out.println on an object the hashcode is returned.
Was this your problem?
If you want a String representation of an object, this object must implement toString(). If you don't the default in the JVM is to print the hash code.
If you want to print a specific field of your object, you should explicitly print that field, through a method if necessary; like System.out.println(student[i].getName());
If you are trying to print a whole array, you should use Arrays.toString().
please override toString() method as currently it is only printing by default implementation of toString() method from Object class which is set to current object's hashcode().
This kind of printing will get the instance address and not a print of it.
Because you want to print a reference type, the VM doesn't know how you want it display or whatever or not some of the fields aren't for printing.
It's apt to you, Overriding "public String toString()" method and implement your own format.