Still learning Java, bit of an idiot and I apologize for the trouble. I have a question with regards to using user input from a main.class with an employee.class with getters and setters and returning those back to the main.class. Is this the correct way of using methods from the employee.class with user input? Would it be okay to just point me to the right direction.
Here's the Employee.class which needed a default value of true.
public class Employee() {
private String id = "100";
private boolean manager = true;
public Employee(String id, String name, int numOfYears) {
this.id = id;
this.name = name;
this.numOfYears = numOfYears;
}
public Employee(String id, String name, int numOfYears, double
monthlySalary, boolean manager) {
this.id = id;
this.name = name;
this.numOfYears = numOfYears;
this.monthlySalary = monthlySalary;
this.manager = manager;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean getManager() {
return manager;
}
public void setManager(boolean manager) {
if (manager == true) {
System.out.println("Yes");
this.manager = manager;
} else {
System.out.println("No");
this.manager = manager;
}
}
}
And here's the Main.class
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter employee ID:");
int i = input.nextInt();
String id = Integer.toString(i);
System.out.println("In management? True/False");
boolean manager = input.nextBoolean();
Employee empId = new Employee(id);
empId.setId(id);
Employee empManager = new Employee();
empManager.setManager();
}
}
Would the correct way to input the user values be
Employee empManager = new Employee(manager);
empManager.setManager();
I'm not sure if I could ask, but I feel like I probably have more errors, if it'd be okay to just nudge in the right direction.
It's not the correct way.
The correct way would be to define a proper constructor:
public Employee(String id, boolean isManager)
{
this.id = id;
this.isManager = isManager;
}
and call it like that:
Employee employee = new Employee(id,isManager);
Brief hint: For booleans, it's a good practice to name them with "isXYZ" - that's why I've changed the name. Also, an if(var == true) can be written as if(var) - the true is implicit.
The right answer is that there is no "right" answer. This is 100% a philosophical question with a number of "right" answers. That said, there are some things most developers will agree with that you need to consider for you to decide which "right" answer is the right one FOR YOU.
What parameters should you pass via constructor? The constructor should be used to enforce REQUIRED values at the time of construction. For example, name and id we can agree should be required fields. But, what about managerName? Maybe the manager has not been assigned at the time of hire for some reason (i.e. position is vacant).
Since it's OK to have setter methods, might as well use them. There is nothing wrong with providing a setter method and use such method to set a value AFTER the object is created. As a general rule, we include getter/setter methods for all fields. HOWEVER, I think it is better to decide which fields (if any) are constant and provide setters (obviously) for variable fields only.
For argument's sake, let's assume that a person should not be able to change his or her name. IN that case, I would design my Employee class like this:
public class Employee {
private final String name; // Required (constant)
private final String id; // Required (constant)
private String phoneNo; // optional
private String managerName; // "optional"
private boolean isManager; // required (variable)
public Employee (String name, String id) {
this.name = name;
this.id = id;
}
public void setPhoneNo(String phoneNo) { this.phoneNo = phoneNo; }
public void setManagerName(String managerName) { this.managerName = managerName; }
}
Also, consider default values. In Java, Primitive Data Types have default values as follows: numeric primitives have a default value of 0. Boolean primitives default to false, character primitive default to the Unicode character value of NULL (\u0000). This means that, unless you need to override the default value, setting the value might be optional (even though the value is required). What does that mean? In your example, you have a boolean flag to indicate whether an employee is in management. Knowing that the majority of employees are not going to be in management, the above example's constructor should be enough. For someone that is hired as manager, you can provide three-argument constructor to pass "true" to this boolean field OR simply build the employee object with the existing constructor and then use the setter method to set this flag to true.
Employee hector = new Employee("Hector", "100");
hector.setManager(true);
The above will be as acceptable as
Employee hector = new Employee ("Hector", "100", true);
Having this three-argument constructor does not invalidate the need for the two argument one. It is fine to keep both. However, if you must do so, use a telescoping pattern...
public Employee (String name, String id, boolean isManager) {
this(name, id); // calling the two-arg constructor
this.isManager = isManager;
}
Related
I have a nested POJO structure defined something like this,
public class Employee {
private String id;
private Personal personal;
private Official official;
}
public class Personal {
private String fName;
private String lName;
private String address;
}
public class Official {
private boolean active;
private Salary salary;
}
public class Salary {
private double hourly;
private double monthly;
private double yearly;
}
I get updates from a service with dot annotaion on what value changed, for ex,
id change --> id=100
address change --> personal.address=123 Main Street
hourly salary change --> official.salary.hourly=100
This POJO structure could be 3-4 level deeps. I need to look for this incoming change value and update the corresponding value in POJO. What's the best way of doing it?
If you would like to create Java objects that allows you to edit fields. You can specify your object fields with the public/default/protected access modifiers. This will enable you to get and set fields such as personal.address or official.salary.hours
This approach is typically frowned upon as the object is no longer encapsulated and any calling methods are welcome to manipulate the object. If these fields are not encapsulated with getters and setters, your object is no longer a POJO.
public provides access from any anywhere.
default provides access from any package
protected provides access from package or subclass.
public class Employee {
public String id;
public Personal personal;
public Official official;
}
public class Personal {
public String fName;
public String lName;
public String address;
}
Here's a quick approach using reflection to set fields dynamically. It surely isn't and can't be clean. If I were you, I would use a scripting engine for that (assuming it's safe to do so).
private static void setValueAt(Object target, String path, String value)
throws Exception {
String[] fields = path.split("\\.");
if (fields.length > 1) {
setValueAt(readField(target, fields[0]),
path.substring(path.indexOf('.') + 1), value);
return;
}
Field f = target.getClass()
.getDeclaredField(path);
f.setAccessible(true);
f.set(target, parse(value, f.getType())); // cast or convert value first
}
//Example code for converting strings to primitives
private static Object parse(String value, Class<?> type) {
if (String.class.equals(type)) {
return value;
} else if (double.class.equals(type) || Double.class.equals(type)) {
return Long.parseLong(value);
} else if (boolean.class.equals(type) || Boolean.class.equals(type)) {
return Boolean.valueOf(value);
}
return value;// ?
}
private static Object readField(Object from, String field) throws Exception {
Field f = from.getClass()
.getDeclaredField(field);
f.setAccessible(true);
return f.get(from);
}
Just be aware that there's a lot to improve in this code (exception handling, null checks, etc.), although it seems to achieve what you're looking for (split your input on = to call setValueAt()):
Employee e = new Employee();
e.setOfficial(new Official());
e.setPersonal(new Personal());
e.getOfficial().setSalary(new Salary());
ObjectMapper mapper = new ObjectMapper();
setValueAt(e, "id", "123");
// {"id":"123","personal":{},"official":{"active":false,"salary":{"hourly":0.0,"monthly":0.0,"yearly":0.0}}}
setValueAt(e, "personal.address", "123 Main Street");
// {"id":"123","personal":{"address":"123 Main Street"},"official":{"active":false,"salary":{"hourly":0.0,"monthly":0.0,"yearly":0.0}}}
setValueAt(e, "official.salary.hourly", "100");
// {"id":"123","personal":{"address":"123 Main Street"},"official":{"active":false,"salary":{"hourly":100.0,"monthly":0.0,"yearly":0.0}}}
My question is: What is the best way to write the constructor of a Java class with fields that are initialized through stdin?
For example suppose that I have an Employee class that looks like:
Public class Employee {
private int empID;
private String empName;
private List<Role> empRoles;
{....}
}
I can write all the setters and getters for this class. Of course, the Role class will have its own file.
Also suppose that I make my setters for the first two fields as follows, in order to enable the end user to initialize the fields:
public void setEmpID() {
System.out.println("Please enter the employee ID");
Scanner s = new Scanner (System.in);
this.empID = s.nextInt();
public void setEmpName() {
System.out.println("Please enter the employee name");
Scanner s = new Scanner (System.in);
this.empName = s.next();
}
then:
Can I use such setters in a constructor that overrides the default
constructor.
Is this the best way to write such constructors?
Is it better to move the Scanner object I am creating in each setter to the constructor and make it as an argument for the setters
e.g:
public void setEmpName(Scanner s) {
...
this.empName = s.next();
}
As you can see, this may be a design question rather than just "coding".
Many thanks for your help.
Actually, you don't rely on a way that uses a specific constructor to populate fields of the object but a no arg constructor.
You indeed chose a setter approach to populate fields of the Employee instance after invoking new Employe().
But this setter approach is complex as you mix too many responsibilities : taking user input and setting state of the object.
Can I use such setters in a constructor that overrides the default
constructor.
No, it makes no sense : constructor and setters are two distinct ways and you cannot override one with the other.
You could however invoke setters from the constructor by relying on a Scanner instance to take user input but similarly to your actual setters approach, it seems a awkward approach as it gives too many responsibilities to the constructor.
Is this the best way to write such constructors?
Using a constructor that populates all fields, that is :
Employee emp = new Employe(id, name, roles)
makes sense if your object is designed to be immutable once it is created.
In your actual case, if your object is not designed to be immutable using constructor or setters is valid but in any case, you should provide setters.
So to answer to your question, you should separate responsibilities (taking user input and setting the object state) and use either setter or constructor approach according to your requirements on instances of Employee :
Employee emp = new Employe(id, name, roles)
or
Employee emp = new Employe();
emp.setId(...);
emp.setName(...);
emp.setRoles(...);
I think that you may be confusing user input/output with program model. The key here is that you should keep the two completely separate. The Employee class should have absolutely no knowledge about what type of UI or I/O is being done to use it, since in this way it can be used in a GUI, in a console program or anywhere else it is needed.
So your Employee constructors should just take in the data needed to create an Employee object, irrespective of its source, and the same for your field getters.
So your getters will look nothing like you've posted and instead be much more plain, much more "dumb" or "ignorant" of user I/O (Scanner, System.in, and the like)
public void getEmpID (int empID) {
this.empID = empID;
}
same for the other fields.
All the I/O stuff -- the Scanner class and such goes elsewhere in your driver class.
Side note: when you use a Scanner based on the System.in your program should create one and only one such beast, create it when needed, and then close and dispose of it only when the program is completely done with it. Otherwise you risk breaking system input by prematurely closing the connection. This is yet another reason not to use your proposed code where you create multiple Scanner objects.
For example....
import java.util.ArrayList;
import java.util.List;
public class Employee {
private int empID;
private String empName;
private List<Role> empRoles;
public Employee(int empID, String empName) {
super();
this.empID = empID;
this.empName = empName;
empRoles = new ArrayList<>();
}
public int getEmpID() {
return empID;
}
public void setEmpID(int empID) {
this.empID = empID;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public List<Role> getEmpRoles() {
return empRoles;
}
public boolean addEmpRole(Role role) {
return empRoles.add(role);
}
public boolean removeEmpRole(Role role) {
return empRoles.remove(role);
}
}
You can then use it elsewhere like so:
import java.util.Scanner;
public class TestEmployee {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("Enter employee ID: ");
int empID = scan.nextInt();
scan.nextLine(); // handle dangling end of line token
System.out.print("Enter employee Name: ");
String empName = scan.nextLine();
Employee employee = new Employee(empID, empName);
// if we are **totally** done with the Scanner, now we may close it
scan.close();
}
}
There are two good answers already but I want to give you one more solution to your problem. As #davidxx already said if your object should be immutable all arguments constructor is a better aproach instead of setters but let's think for the case where you have more fields. For example your employee have salary, experience and other. Your constructor starts to look like this:
Employee employee = new Employee(id, name, roles, salary, experience, ... );
As you can see the constructor starts becoming too long. This is called telescoping constructor. Let's think for the case where your employee has 2-3 required fields and the others are not required. To create this object you'll have to write code like this:
Employee employee = new Employee(id, name, roles, null, null, 0, ... );
This is problematic because :
Passing null to functions may caused you a lot of headaches.
This code is not so readable.
You can add constructor which recieves only fields that you need but then you'll have to add a new constructor(breaking Open-Closed principle) every time when you need to pass a different combination of parameters. Solution for this situation is to use the builder pattern:
public class Employee {
private int id;
private String name;
private List<Role> roles;
private Employee() {
roles = new ArrayList<>();
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public List<Role> getRoles() {
return roles;
}
public static class EmployeeBuilder {
private Employee employee;
public EmployeeBuilder() {
employee = new Employee();
}
public EmployeeBuilder withId(Integer id) {
employee.id = id;
return this;
}
public EmployeeBuilder withName(String name) {
employee.name = name;
return this;
}
public EmployeeBuilder withRole(Role role) {
employee.roles.add(role);
return this;
}
public Employee build() {
return employee;
}
}
}
And then you can create your object like this:
Employee employee = new Employee.EmployeeBuilder()
.withId(1)
.withName("John")
.withRole(role1)
.withRole(role2)
.build();
This question already has answers here:
Invoking all setters within a class using reflection
(4 answers)
Closed 5 years ago.
I have a POJO object and a collection of appropriate data.
import java.util.ArrayList;
import java.util.List;
public class TestPojo {
private String name;
private String number;
private String id;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public static void main(String[] args) {
TestPojo test = new TestPojo();
List<String> sampleData = new ArrayList<>();
sampleData.add("Bob");
sampleData.add("641-613-623");
sampleData.add("id-1451");
sampleData.add("Male");
test.setName(sampleData.get(0));
test.setNumber(sampleData.get(1));
test.setId(sampleData.get(2));
test.setSex(sampleData.get(3));
}
}
My question is how can i fill my POJO object with data in a loop? Is it posible to iterate all object setters and set data from List in appropriate places? I know that reflection can help in this case.
Here is an simple example to call setters via reflection (which needs to be adjusted):
[if this is a good approach, is another question. But to answer your question:]
public static void main(String[] args) throws Exception
{
//this is only to demonstrate java reflection:
Method[] publicMethods = TestPojo.class.getMethods(); //get all public methods
TestPojo testObj = TestPojo.class.newInstance(); //when you have a default ctor (otherwise get constructors here)
for (Method aMethod : publicMethods) //iterate over methods
{
//check name and parameter-count (mabye needs some more checks...paramter types can also be checked...)
if (aMethod.getName().startsWith("set") && aMethod.getParameterCount() == 1)
{
Object[] parms = new Object[]{"test"}; //only one parm (can be multiple params)
aMethod.invoke(testObj, parms); //call setter-method here
}
}
}
You can also save all setter-methods in an list/set for later re-use...
But as others already said, you have to be careful by doing so (using reflection)!
Cheers!
You can't easily - and you shouldn't.
You see, your POJO class offers some setters. All of them have a distinct meaning. Your first mistake is that all of these fields are strings in your model:
gender is not a string. It would rather be an enum.
"number" is not a string. It should rather be int/long/double (whatever the idea behind that property is)
In other words: you premise that "input" data is represented as array/list is already flawed.
The code you have written provides almost no helpful abstractions. So - instead of worrying how to call these setter methods in some loop context - you should rather step back and improve your model.
And hint: if this is really about populating POJO objects from string input - then get your string into JSON format, and use tools such as gson or jackson to do that (reflection based) mapping for you.
"Iterating over methods" seems pretty much of a wrong idea in OO programming. You could simply add a constructor to your class setting all of your attributes, and then just call that constructor in a loop as desired to create new objects with data you desire.
In your class define:
public TestPojo(String name, String number, String id, String sex){
this.name = name;
this.number = number;
this.id = id;
this.sex = sex;
}
Also using a List makes no much sense here. I'd recommend using a HashMap to then iterate over it in a for loop making proper calls of the above constructor.
Well, i was trying to pass arraylist of objects from one activity to another. I have 2 constructors in the class Student.
If, i use, Serializable than the code is like below:
#SuppressWarnings("serial")
public class Student implements Serializable
{
private int studentdID;
private String studentName;
private String studentDept;
public Student(){}
public Student(String name, String dpt)
{ this.studentName = name;
this.studentDept = dpt;}
public Student(int id, String name, String dpt)
{ this.studentdID = id;
this.studentName = name;
this.studentDept = dpt; }
public int getstudentdID() { return studentdID; }
public void setstudentdID(int studentdID) {this.studentdID = studentdID;}
public String getstudentName() { return studentName;}
public void setstudentName(String studentName) {this.studentName = studentName;}
public String getstudentDept() { return studentDept; }
public void setstudentDept(String studentDept) { this.studentDept = studentDept;}
}
But the problem i am facing is that how am i going to do this with parcelable? How am i going to set the values of the variables in class-like i did with Serializable? I mean separately using 2 constructors-one without ID another without the ID?
Did you read how Parcelable works?
You need only one constrcutor for parcelable to read what you pass to it, and Parcelable interface will add a method writeToParcel where you put the data to save.
It's not an automatic process like Serializable, everything is up to you.
The constructor which Parcelable will use will accept only one argument Parcel where you will find some methods like read*(KEY) to read back values.
And in writeToParcel you will write in the Parcel (the argument of the method) the values you want pass to pass with write*(KEY, VALUE).
Parcelable don't care about your constructors or fields.
P.S You will need a CREATOR too. Read some tutorial online to know more about it if you need.
Marco's answer explains why Parcelable doesn't automatically decide what constructor to use - it can't.
However, there is a way around this. Use Parcel.dataAvail(), which
Returns the amount of data remaining to be read from the parcel. That
is, dataSize()-dataPosition().
For example,
public Student(){}
public Student(String name, String dpt)
{
this.studentName = name;
this.studentDept = dpt;}
public Student(int id, String name, String dpt)
{ this.studentdID = id;
this.studentName = name;
this.studentDept = dpt;
}
public Student(Parcel in) {
name = in.readString();
dpt = in.readString();
if(in.dataAvail() > 0) // is there data left to read?
id = in.readInt();
}
^ The above constructor will allow for the necessary variables to be instantiated correctly. Also, you define writeToParcel() something like:
public void writeToParcel(Parcel out) {
out.writeString(name);
out.writeString(dpt);
//0 is the default value of id if you didn't initialize it like
// in the first constructor. If it isn't 0, that means it was initialized.
if(id != 0)
out.writeInt(id);
}
Of course, you'll need to define your CREATOR like so:
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
public Student createFromParcel(Parcel in) {
return new Student(in);
}
public Student[] newArray(int size) {
return new Student[size];
}
};
#u3l solution is not required..how many constructors are there it doesn't matter.
simple it works go as normal implementation.
I mean no special care is required when multiple constructors present in parcelable.
I am working on a homework assignment. I am confused on how it should be done.
The question is:
Create a class called IDCard that contains a person's name, ID number,
and the name of a file containing the person's photogrpah. Write
accessor and mutator methods for each of these fields. Add the
following two overloaded constructors to the class:
public IDCard() public IDCard(String n, int ID, String filename)
Test your program by creating different ojbects using these two
constructors and printing out their values on the console using the
accessor and mutator methods.
I have re-written this so far:
public class IDCard {
String Name, FileName;
int ID;
public static void main(String[] args) {
}
public IDCard()
{
this.Name = getName();
this.FileName = getFileName();
this.ID = getID();
}
public IDCard(String n, int ID, String filename)
{
}
public String getName()
{
return "Jack Smith";
}
public String getFileName()
{
return "Jack.jpg";
}
public int getID()
{
return 555;
}
}
Let's go over the basics:
"Accessor" and "Mutator" are just fancy names fot a getter and a setter.
A getter, "Accessor", returns a class's variable or its value. A setter, "Mutator", sets a class variable pointer or its value.
So first you need to set up a class with some variables to get/set:
public class IDCard
{
private String mName;
private String mFileName;
private int mID;
}
But oh no! If you instantiate this class the default values for these variables will be meaningless.
B.T.W. "instantiate" is a fancy word for doing:
IDCard test = new IDCard();
So - let's set up a default constructor, this is the method being called when you "instantiate" a class.
public IDCard()
{
mName = "";
mFileName = "";
mID = -1;
}
But what if we do know the values we wanna give our variables? So let's make another constructor, one that takes parameters:
public IDCard(String name, int ID, String filename)
{
mName = name;
mID = ID;
mFileName = filename;
}
Wow - this is nice. But stupid. Because we have no way of accessing (=reading) the values of our variables. So let's add a getter, and while we're at it, add a setter as well:
public String getName()
{
return mName;
}
public void setName( String name )
{
mName = name;
}
Nice. Now we can access mName. Add the rest of the accessors and mutators and you're now a certified Java newbie.
Good luck.
You need to remove the static from your accessor methods - these methods need to be instance methods and access the instance variables
public class IDCard {
public String name, fileName;
public int id;
public IDCard(final String name, final String fileName, final int id) {
this.name = name;
this.fileName = fileName
this.id = id;
}
public String getName() {
return name;
}
}
You can the create an IDCard and use the accessor like this:
final IDCard card = new IDCard();
card.getName();
Each time you call new a new instance of the IDCard will be created and it will have it's own copies of the 3 variables.
If you use the static keyword then those variables are common across every instance of IDCard.
A couple of things to bear in mind:
don't add useless comments - they add code clutter and nothing else.
conform to naming conventions, use lower case of variable names - name not Name.