Using random enum to generate objects in java - java

There are four classes that interact with my project. The aim is to generate an object using enum, using the random values from enum.
The EthicalEngine class. I'll call the method from another class called ScenarioGenerator.
The Person class inherited from the Character abstract class.
I am not sure whether my method of initialization is correct or not. My idea is to initialize the instance of the Person in the ScenarioGenerator class, and use a method getRandomPerson() to call the constructor.
But I stuck, keep getting NullPointerException when I called the method.
Here is part of my Character class:
abstract class Character {
private int age;
private Gender gender;
private BodyType bodyType;
protected Profession profession;
protected AgeCategory ageCategory;
protected boolean isPregnant;
public enum Gender {
MALE, FEMALE, UNKNOWN;
}
public enum BodyType {
AVERAGE, ATHLETIC, OVERWEIGHT, UNSPECIFIED;
}
public enum Profession {
DOCTOR, CEO, CRIMINAL, HOMELESS, UNEMPLOYED, MUSICIAN, BOXER ,UNKNOWN, NONE;
}
public Character(int age, Profession profession, Gender gender, BodyType bodyType, boolean isPregnant) {
this.age = age;
this.profession = profession;
this.gender = gender;
this.bodyType = bodyType;
this.isPregnant = isPregnant;
}
part of my Person class:
Person(int age, Profession profession ,Gender gender, BodyType bodyType, boolean isPregnant) {
super(age, profession, gender, bodyType, isPregnant);
}
public Profession getProfession () { //use getter to generate a random value
//only adults have profession
if (getAge()<=16 || getAge()>68) {
return Profession.NONE;
} else {
return Profession.values()[new Random().nextInt(Profession.values().length)];
}
//other getters and setters
}
Part of my ScenarioGenerator class:
public class ScenarioGenerator {
private Person person;
private Animal animal;
private Scenario scenario;
private Random random = new Random();
private int passengerCountMinimum;
private int passengerCountMaximum;
private int pedestrianCountMininum;
private int pedestrianCountMaximum;
public ScenarioGenerator() {
random.setSeed(random.nextInt());
}
public ScenarioGenerator(long seed) {
this.random = new Random(seed);
}
public Person getRandomPerson() {
//need age, gender, bodyType, profession, pregnancy
Person people = new Person(person.getAge(), person.getProfession(), person.getGender(),person.getBodyType(), person.isPregnant());
return people;
}
Part of my EthicalEngine class:
public class EthicalEngine {
public static void main(String[] args) throws Exception {
EthicalEngine ethicalEngine = new EthicalEngine();
ScenarioGenerator scenarioGenerator = new ScenarioGenerator();
scenarioGenerator.getRandomPerson();
}

you can generate random number and select all values
import java.util.Random;
public class ScenarioGenerator {
public Person getRandomPerson() {
Random rand = new Random();
// max age
int age = rand.nextInt(100);
// no of profession - 1
int profession = rand.nextInt(8);
// no of gender - 1
int gender = rand.nextInt(2);
// no of bodyType - 1
int bodyType = rand.nextInt(3);
int pragnency = rand.nextInt(2);
//need age, gender, bodyType, profession, pregnancy
Person people = new Person(age, Profession.values()[profession], Gender.values()[gender],BodyType.values()[bodyType], pragnency == 1 ? true : false);
return people;
}
}

Related

Creating a method in JAVA to print the content of an ArrayList calling a specific format of another class

In this example, I would like to add students of a school into an ArrayList and print the array list with Polymorphism format from another method defined in another class.
import java.util.ArrayList;
class Student{
public static String name;
public static String gender;
public static int age;
//setting default values for the member variables
public Student(){
name = "default name";
gender = "default gender";
age = 0;
}
//constructor of the parameters for the name, gender, and age.
public Student(String name, String gender, int age){
Student.name = name;
Student.gender = gender;
Student.age = age;
}
// Polymorphism to print with a specific format
public static void printInfo(){
System.out.println(name+", "+gender+", "+age+"\n");
}
}
// creating a class for Male students
class Male extends Student{
private static String gender;
public Male(String name, int age){
super(name, gender, age);
Male.gender = "Male";
}
}
// creating a class for Female students
class Female extends Student{
private static String gender;
public Female(String name, int age){
super(name, gender, age);
Female.gender = "Female";
}
}
// create a class for school to collect all the students
class School{
static ArrayList<Student> students;
public static void addStudent(Student a){
ArrayList<Student> students = new ArrayList<Student>();
students.add(a);
}
public void printAllInfo(){
//call the Student.printInfo method from the Student class
}
}
public class SchoolBuilder{
public static void main(String[] args){
School.addStudent(new Male("Sam",13));
School.addStudent(new Male("John",11));
School.addStudent(new Female("Elle",12));
School.addStudent(new Male("Paul",12));
School.addStudent(new Female("Javinia",11));
School.addStudent(new Male("Paperino",12));
//PRint all by calling School.printAllInfo should print the formatted ArrayList
}
}
The output should be like this:
Sam, Male, 13
John, Male, 11
Elle, Female, 12
Paul, Male, 12
Javinia, Female, 11
Paperino, Male, 12
I am new to JAVA and just can't figure out how to do it. It seems like it's easy.
I've made the two classes for gender because it is easy to add later a CSV file of all males or females and add them into the dataset calling the male and female classes respectively.
Thanks for your time and help with this.
In general, we do this by overriding the toString() method of some class, and then printing that.
Take the following as constructive criticism: there are a bunch of issues here.
You want to avoid the static context in this case, because static
variables belong to a class. Not every student will have the same
name, for example.
Similarly, you wouldn't call Student.function(), you would call this.function() to call that for only that student, not the class student. this is an instance of Student.
You definitely don't want to do ArrayList<Student> students = new
ArrayList<Student>(); within your addStudent() method. You're
resetting your list of students every time you add a student. Keep
that in the class level declaration or better yet, add a
constructor.
import java.util.ArrayList;
class Student{
public String name;
public String gender;
public int age;
//setting default values for the member variables
public Student(){
name = "default name";
gender = "default gender";
age = 0;
}
//constructor of the parameters for the name, gender, and age.
public Student(String name, String gender, int age){
this.name = name;
this.gender = gender;
this.age = age;
}
// Polymorphism to print with a specific format
public String printInfo(){
return name+", "+gender+", "+age+"\n";
}
}
// creating a class for Male students
class Male extends Student{
private static String gender;
public Male(String name, int age){
super(name, gender, age);
Male.gender = "Male";
}
}
// creating a class for Female students
class Female extends Student{
private static String gender;
public Female(String name, int age){
super(name, gender, age);
Female.gender = "Female";
}
}
// create a class for school to collect all the students
class School{
ArrayList<Student> students = new ArrayList<Student>();
public void addStudent(Student a) {
students.add(a);
}
public void printAllInfo(){
//call the Student.printInfo method from the Student class
}
public String toString() {
String string = "";
for (Student s : students) {
string += s.printInfo();
}
return string;
}
}
public class Work{
public static void main(String[] args){
School sch = new School();
sch.addStudent(new Male("Sam",13));
sch.addStudent(new Male("John",11));
sch.addStudent(new Female("Elle",12));
sch.addStudent(new Male("Paul",12));
sch.addStudent(new Female("Javinia",11));
sch.addStudent(new Male("Paperino",12));
System.out.println(sch.toString());
}
}
There are some error in your implementation:
The Student object should not has static fields. static means that they're not referred to a specific object, but to the class itself.
The object is a specific implementation of a class. You define a Student class to define how a student looks like, that with a specific instatiation you create a student.
When you declare the class, you say that a student has in general a name, gender and age.When you istantiate a student with the constructor (new Student("Sam", "Male", 13)) you define the specific implementation.
class Student {
public String name;
public String gender;
public int age;
//setting default values for the member variables
public Student(){
name = "default name";
gender = "default gender";
age = 0;
}
//constructor of the parameters for the name, gender, and age.
public Student(String name, String gender, int age){
this.name = name;
this.gender = gender;
this.age = age;
}
Class Male and Female has to be changed. It's not wrong to extend the Student class to set a default value to the gender field. It would be more useful to extend it if, for example, the Male class has a specific field (for example favouriteSoccerPlayer) which instead a general student should not have. In that case the Male class would inherit the fields from the parent class (Student) and add another extra field:
class Male extends Student {
private String favouriteSoccerPlayer;
public Male(String name, int age) {
super(name, "Male", age); // call the constructor of the super class
}
public Male(String name, int age, String favouriteSoccerPlayer) {
super(name, "Male", age); // call the constructor of the super class
this.favouriteSoccerPlayer = favouriteSoccerPlayer;
}
// getter and setter for only this field
}
then you can for example do something like this:
Male male = new Male("John", 32, "Maradona");
System.out.println(male.getName());
and you'll call the method that the Male object inherit from the Student class.
This would be class Male, same is for Female:
// creating a class for Male students
class Male extends Student{
private static final String gender = "Male";//This should be constant for all instances of class and because of that it is "static final"
public Male(String name, int age){
super(name, gender, age);
}
}
Next School would not have any static thing in it.
import java.util.ArrayList;
// create a class for school to collect all the students
class School {
private ArrayList<Student> students; //Should not be static, and initialization moved in constructor
public School() {
students = new ArrayList<>();
}
public void addStudent(Student a) {
students.add(a);
}
public void printAllInfo() {
for (Student s : students) {
s.printInfo();
}
}
}
Finally main class should create School instance, add students and print them:
public class SchoolBuilder{
public static void main(String[] args){
School school=new School();
school.addStudent(new Male("Sam",13));
school.addStudent(new Male("John",11));
school.addStudent(new Female("Elle",12));
school.addStudent(new Male("Paul",12));
school.addStudent(new Female("Javinia",11));
school.addStudent(new Male("Paperino",12));
school.printAllInfo();
}
}
Last, this method in Student should not have \n in String as it will add one more new line.
// Polymorphism to print with a specific format
public void printInfo(){
System.out.println(name+", "+gender+", "+age+"\n");
}

retriving specific data from LinkedList

I want to find students whose gender is female by using streams
Student class
public class Student {
private String first;
private String last;
private int ID;
private Gender gender;
int next=0;
List<Course> courses=new LinkedList<>();
List<Student> students=new LinkedList<>();
public Student(String first, String last, int iD, Gender gender) {
this.first = first;
this.last = last;
ID = iD;
//this.gender = gender;
}
public void enroll(Course c) {
courses.add(c);
}
public void isFemale(){
Student s;
return s.gender=Gender.F;
}
}
enum class for genders
public enum Gender {
M,F;
private Gender gender;
}
main class
public class Main {
public static void main(String[] args) {
List<Student> studentsOfClass=new LinkedList<>();
studentsOfClass.add(new Student("john","smith",01,Gender.M));
studentsOfClass.add(new Student("mick","tayson",05,Gender.M));
studentsOfClass.add(new Student("sara","conor",04,Gender.F));
studentsOfClass.add(new Student("Tana","smith",02,Gender.F));
Course c1=new Course("fiologiya","anna",0234);
Course c2=new Course("mathematics","maria",1134);
Course c3=new Course("phisics","luisa",0534);
studentsOfClass.stream().limit(3).forEach(s->s.enroll(c1));
Collection<Student> femaleStudents= studentsOfClass.stream().filter(Student::isFemale).collect(Collectors.toList());
}
}
You are using the Stream methods correctly, but your isFamele method is wrong. It should return boolean and check the gender of the current Student.
It should be :
public boolean isFemale()
{
return gender==Gender.F;
}
You should also unremark this constructor line - //this.gender = gender; - and probably remove private Gender gender; from the Gender enum.
In addition, you can change the type of femaleStudents from Collection to List<Student>, which is more accurate.

Constructor + Inheritance support

I am fairly new to Inheritance, and I'm not sure if I am doing it right but I seem to be on the right track. The program runs fine except the output I am getting isn't right. I think the problem is to do with my constructors.
public class Person {
protected static String name;
protected static int birthYear;
public Person(String name, int birthYear) {
}
public String name (String n) {
n = name;
return n;
}
public int birthYear (int bY) {
bY = birthYear;
return bY;
}
#Override
public String toString() {
return String.format(name + birthYear);
}
}
public class Student extends Person {
protected String major;
public Student(String name, int birthYear, String major) {
super(name, birthYear);
major = "";
}
public String major(String maj) {
maj = major;
return maj;
}
public String toString() {
super.toString();
return super.toString() + major;
}
}
public class Instructor extends Person {
protected static int salary;
public Instructor(String name, int birthYear, int salary) {
super(name, birthYear);
salary = 0;
}
public int salary(int sal) {
sal = salary;
return sal;
}
public String toString() {
super.toString();
return super.toString() + salary;
}
}
public class PersonTester {
public static void main(String[] args) {
Person p = new Person("Perry", 1959);
Student s = new Student("Sylvia", 1979, "Computer Science");
Instructor e = new Instructor("Edgar", 1969, 65000);
System.out.println(p);
System.out.println("Expected: Person[name=Perry,birthYear=1959]");
System.out.println(s);
System.out.println("Expected:" +
"Student[super=Person[name=Sylvia,birthYear=1979],major=Computer]");
System.out.println(e);
System.out.println("Expected:" + "Instructor[super=Person[name=Edgar,birthYear=1969],salary=65000.0]");
}
}
OUTPUT I AM GETTING:
null0
Expected: Person[name=Perry,birthYear=1959]
null0null
Expected: Student[super=Person[name=Sylvia,birthYear=1979],major=Computer Science]
null00
Expected: Instructor[super=Person[name=Edgar,birthYear=1969],salary=65000.0]
Try changing your constructor in Person to:
public Person(String name, int birthYear) {
this.name = name;
this.birthYear = birthYear;
}
Currently, the constructor has an empty body, so when you call super(name, birthYear); in the subclass constructor, nothing actually happens.
Your Student constructor also has an error. You forgot to initialize the major field.
public Student(String name, int birthYear, String major) {
super(name, birthYear);
this.major = major;
}
You have the same problem in the Instructor constructor...
public Instructor(String name, int birthYear, int salary) {
super(name, birthYear);
this.salary = salary;
}
Finally, you need to take away the static keywords before the fields in Person. This is because static ensures, that there will always be one (and only one) instance of those fields per class, as opposed to one per instance, like you want it to be:
protected String name;
protected int birthYear;
Same thing for the salary field in Instructor.
n = name; this causing your problem. It must be name = n;. All your setter function contain this problem, correct them all and tell me result.

java constructor handling lack of arguments

i have this code here for a person details and the person should be intialized always whatever the number of possible arguments given ,like for example only height and age or salary and age
and i find it difficult to declare a constructor for every combination of arguments , is there a more optimal solution than that ??
class person {
public static final int defalut_salary=1000;
public static final int default_age=20;
public static final double default_height=6;
public static final String default_name="jack";
protected int salary;
protected int age;
protected double height;
protected String name;
person(){
}
}
I would suggest using the Builder pattern:
public final class Person {
private final int salary;
private final int age;
private final double height;
private final String name;
public Person(int salary, int age, double height, String name) {
this.salary = salary;
this.age = age;
this.height = height;
this.name = name;
}
// Getters or whatever you want
public static class Builder {
// Make each field default appropriately
private int salary = 1000;
private int age = 20;
private double height = 6;
private String name = "jack";
public Builder setSalary(int salary) {
this.salary = salary;
return this;
}
// Ditto for other properties
public Person build() {
return new Person(salary, age, height, name);
}
}
}
Usage:
Person person = new Person.Builder().setAge(25).setHeight(15).build();
You can perform validation in the Person constructor, and if you want to make any of the fields mandatory, you could take those in the Builder constructor.
Initialize all fields in a default constructor and use methods to set values in the desired fields, for example like this:
class A{
Field a;
Field b;
Field c;
public A(){
a = SOME_VALUE;
b = SOME_VALUE;
c = SOME_VALUE;
}
public A withA(Field a){ this.a = a; return this; }
public A withB(Field b){ this.b = b; return this; }
public A withC(Field c){ this.c = c; return this; }
/* other code */
}
Then you can use it like this:
A a = new A().withB(SOME_OTHER_VALUE).withC(YET_DIFFERENT_VALUE);
If don't want the fields' values to be changed with subsequent calls to withX() methods, you can use a full-fledged builder pattern.
You could define the constructor to take primitive wrapper classes (like java.lang.Integer or java.lang.Double) instead of primitives. The difference is that this allows you to pass null instead of a value. You can then check them for null. When they are null, you assign the default value. When they aren't, you assign their value.
public Person(Integer salary, Integer age, Double height, String name) {
if (salary == null) this.salary = salary else this.salary = default_salary;
if (age == null) this.age = age else this.age = default_age;
//...
}
The invocation new Person(1200, null, 5.3, null); would mean "create a person with start salary 1200, default age, height 5.3 and default name".
Another approach is to use the builder pattern as shown in the answer by Jon Skeet. It is less concise, but more readable.

how do is this the correct way of writing this <class name> <object name > = new constructor name?

can some one please help me am having a compilation error with the last part of this code
its saying create constructor please help
public class Officer {
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
System.out.print("Enter the name of the Soldier: ");
String name = input.nextLine();
System.out.print("Enter the sex of the Soldier: ");
String sex = input.nextLine();
System.out.print("Enter the Age of the Soldier: ");
String age = input.nextLine();
Soldier soldier = new Soldier(name, sex, age);
}
}
package officer;
public class Soldier {
private String soldierName;
private int soldierAge;
private char soldierSex;
public void Soldier( String name, char sex, int age) {
soldierName = name;
soldierSex = sex;
soldierAge = age;
}
public String getSoldierName() {
return soldierName;
}
public char getSoldierSex() {
return soldierSex;
}
public int getSoldierAge() {
return soldierAge;
}
}
The class Soldier needs to define a matching constructor
public Soldier (String name, String sex, String age) {
// do stuff
}
This is the method that what be executed, when you call new Soldier(name, sex, age)
It ok, except:
sex should be en enum type
age should be an integer (or float) type
you should validate user input
An SEX enum:
public enum SEX {
MALE, FEMALE
}
A constructor:
public Soldier (String name, SEX sex, int age) {
}
You would need something like:
public class Soldier {
public Soldier(String name, String sex, int age) {
}
}
edit: with the new info provided you should delete the void in the public void Soldier since void would mean public void Soldier is a method of class Soldier while it's supposed to be the constructor.

Categories

Resources