Loop over object setters java [duplicate] - java

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.

Related

Java nested POJO update based on dot annotation

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}}}

How to access an object's fields/methods by their name as a string

Lets say I have a class
class A {
string name;
int age;
string gender;
//assuming all the constructors, getters and setters are present
}
for purpose of simplicity, lets assume all these members are public and to access them I create an object of that class as follows
A a = new A();
is there a way to access the each member as follows
String string = "age"
a.string
and get the age of the object and so on.
similarly, lets say I have a getter and can I access it using
String string = "getAge()";
a.string;
I am an beginner java programmer trying to optimize a code written in swift (needless to say I am a novice in swift), which has a class with more than 50 members and setting/getting each of them in some other module gets very tedious.
Just wondering if this is possible in either of the programming languages. In java I assume something like this might be possible using class reflection, but not very sure.
Well, you can use reflection, and do something like:
A a = new A();
Class cls = a.getClass();
//read a method value
String methodName = "getAge";
Method method = cls.getDeclaredMethod(methodName);
int methodReturnedResult = method.invoke(a, null);
//read a field value
String fieldName = "age";
Field field = cls.getDeclaredField(fieldName);
int fieldValue = field.get(a);
This is another example
Java Reflection tutorial
Though it is important to note that reflection wasn't meant for these cases and it isn't considered a good design to use reflection in these scenarios. What you need to do is to use IDE's abilities to generate setters and getters for you automatically.
Which IDE do you use? Most Java IDE's has the ability to generate getters and setters automatically according to the class fields.
This is how you do it in Eclipse, Netbeans, Intellij and in Android Studio.
As explained here (with an example), you can use java reflection to check whether class contains a field and get the value of that field.
Also, making the fields public isn't a good idea, they should be private and accessed only via getters and setters.
If you have to use reflation, below should work.
Class A
class A {
String name;
int age;
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;
}
}
Utility method in your class
public Object get(String methodName, A a) throws Exception {
Object ret = null;
if(a != null){
Class<A> cl = A.class;
Method method = cl.getDeclaredMethod(methodName);
ret = method.invoke(a);
}
return ret;
}
public void set(String methodName, Object value, A a) throws Exception{
Class<A> cl = A.class;
Method method = cl.getDeclaredMethod(methodName, value.getClass());
method.invoke(a, value);
}
Test it
public void testIt() throws Exception{
A a = new A();
set("setName", "xyz", a);
String name = (String) get("getName",a);
System.out.println(name);
}
Note: be careful on boxed type i.e. int is represented as Integer. And good amount of null checks.

How to create get and set methods for parameters in a class? [duplicate]

This question already has answers here:
How do getters and setters work?
(6 answers)
Closed 7 years ago.
I have a class I created.
public class mailCustomer {
public static void main(String[] args) {
String Name;
int Id;
String Address;
Boolean IsPack;
}
}
I need to creat get and set methods for my parametrs, Name, Id,Address, IsPack.
how do I do that, and where do I write them? after the "main" method? in the "main" method?
Firstly, you need to declare the variables at the class level so that they can be used from anywhere within the class. Then after that you simply create a set and get method for each variable, like so
public class MailCustomer {
String name;
int id;
String address;
boolean isPack;
public static void main(String[] args) {
}
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public void setAddress(String address) {
this.address = address;
}
public void setIsPack(boolean isPack) {
this.isPack = ispack;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public String getAddress() {
return address;
}
public boolean getIsPack() {
return isPack;
}
}
It also appears that you have your naming conventions a little mixed up. In java, class names are capitalized, whereas variable and method names are camelCased
First, delete the main method from there. You are creating a class called mailCustomer that will create you object type of mailCustomer.
For this, you need three things: attributes (you have them there), a constructor and get/set methods. I will show you with a example, and you can guide from there. My class will be 'Rabbit' and it will have:
Attributes
-String eyes: Eye colour.
-String race: Where is it from.
Constructor
It will have one constructor, that will use both parameters.
Methods
It will have two getters and two setters, both for each attribute.
Here's my code for this class:
public class Rabbit{
//Attributes
private String eyes;
private String race;
//Constructor
public Rabbit(String colour, String where){
this.eyes = colour;
this.race = where;
}
//Methods get/set
public String getEyes(){
return this.eyes;
}
public String getRace(){
return this.race;
}
public void setEyes(String colour){
this.eyes = colour;
}
public void setRace(String where){
this.race = where;
}
}
As you can see, you will use get methods to return an specific attribute from the class; and set methods will be used if you want to change one of the attributes from a created object (in my case, from a created 'Rabbit').
Later, if you want to make use of this class, you will create your Main class, into the same package where 'Rabbit' class is created.
package rabbit;
public static void main(String[] args){
Rabbit George = new Rabbit("brown","spanish");
}
Now try to do this with your class. I hope it helped you!
public static void main(String[] args) {
String Name;
int Id;
String Address;
Boolean IsPack;
}
You can't create getters and setters for these, since they are not created in your class, but locally in your main method. What you want is:
public class MyClass{
String Name;
int Id;
String Address;
Boolean IsPack;
// getter for Name
public String getName(){
return this.Name;
}
// setter for Name
public void setName(String name){
this.Name = name;
}
public static void main(String[] args) {
}
}
For these you'll be able to create getters and setters.
It's (most likely) best to declare them private, though.
Also: following naming conventions could help other people easier read your code. Name (with capital N) is more suited as name of a class, while name (lowercase n) is the name of a variable.
As already said it seems that you are not familiar with Object Oriented Programming. It does not care. I just want to say that you can save a lot of time and improve your classes readability using lombok to automatically generate your getters and setters using annotations. You can find an example here : LOMBOK

How to use Parcelable for a class which has multiple constructors?

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.

Java - Using Accessor and Mutator methods

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.

Categories

Resources