Since you are using JPA, have you tried the JPA 2 metamodel (javax.persistence.metamodel). This will give you information about your JPA entities from the JPA metadata:
entityManager.getMetamodel().entity(entityClass). getAttributes();
Answer from bdoughan on Stack OverflowSince you are using JPA, have you tried the JPA 2 metamodel (javax.persistence.metamodel). This will give you information about your JPA entities from the JPA metadata:
entityManager.getMetamodel().entity(entityClass). getAttributes();
When using reflection, you do not need to necessarily invoke the getters in the objects (if the getters only return the value and don't contain any special logic), even if the fields are private (See setAccessible).
As for performance, we are doing something similar in our current project and haven't had any problems yet (at worst, the handler checking the annotated fields on object and building JSON-data from them via reflection is traversing deeply nested object-trees (collections within collections) of up to hundreds of objects, each of which can contain from a handful to several dozen fields).
java - How do I iterate over class members? - Stack Overflow
java - iterate over POJO properties and set it to another object - Stack Overflow
reflection - Loop over object setters java - Stack Overflow
reflection - How to iterate through all properties of a Java bean - Stack Overflow
Sure. Check out the Apache Commons BeanUtils lib. There you can use copyProperties(Object dest, Object orig)
Well you can use reflection to do that in a loop if you don;t want to use the commons library, although using tried and tested code seem to be the wiser choice if you don't have a problem with adding the library to your existing application.
Edit:
This should be enough for you
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
Although I don't know about the performance of this solution vs ApacheCommons I don't think there will be a huge difference.
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.
getDeclaredFields()
for (Field field : yourObject.getClass().getDeclaredFields()) {
//do stuff
}
I strongly recommend to use an existing library and to avoid reflection in this case! Use JPA or Hibernate for database uses, use JAXB or similar for JSON/XML/other serialization, etc.
However, if you want to see what an example code would look like you can have a look at this:
package myOwnPackage;
import java.lang.reflect.Field;
class Address {
private String addr1;
private String addr2;
private String city;
private Zip zip;
}
class Contact {
private String phone;
private String email;
}
class Employee {
private String id;
private String name;
private int age;
private Address addr;
private Contact cont;
public void setAddr(Address addr) {
this.addr = addr;
}
}
class Zip {
private String zipCd;
private String zipExt;
}
public class Main {
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
Employee employee = new Employee();
employee.setAddr(new Address());
printFields("", employee);
}
private static void printFields(String prefix, Object container) throws IllegalAccessException {
Class<? extends Object> class1 = null;
Package package1 = null;
if (container != null)
class1 = container.getClass();
if (class1 != null)
package1 = class1.getPackage();
if (package1 == null || !"myOwnPackage".equals(package1.getName())) {
System.out.println(container);
return;
}
for (Field field : class1.getDeclaredFields()) {
System.out.print(prefix+field.getName()+": ");
// make private fields accessible
field.setAccessible(true);
Object value = field.get(container);
printFields(prefix+" ", value);
}
}
}
Downsides of my code:
- This code uses reflection, so you are limited at the depth of fields
- Inherited fields are not printed
Use getDeclaredFields on [Class]
ClasWithStuff myStuff = new ClassWithStuff();
Field[] fields = myStuff.getClass().getDeclaredFields();
for(Field f : fields){
Class t = f.getType();
Object v = f.get(myStuff);
if(t == boolean.class && Boolean.FALSE.equals(v))
// found default value
else if(t.isPrimitive() && ((Number) v).doubleValue() == 0)
// found default value
else if(!t.isPrimitive() && v == null)
// found default value
}
(http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html)
Yes, with reflection.
Use the Class object to access Field objects with the getFields() method.
Field[] fields = ClassWithStuff.class.getFields();
Then loop over the fields. This works because all fields you have declared are public. If they aren't, then use getDeclaredFields(), which accesses all Fields that are directly declared on the class, public or not.
What about entrySet()
HashMap<String, Person> hm = new HashMap<String, Person>();
hm.put("A", new Person("p1"));
hm.put("B", new Person("p2"));
hm.put("C", new Person("p3"));
hm.put("D", new Person("p4"));
hm.put("E", new Person("p5"));
Set<Map.Entry<String, Person>> set = hm.entrySet();
for (Map.Entry<String, Person> me : set) {
System.out.println("Key :"+me.getKey() +" Name : "+ me.getValue().getName()+"Age :"+me.getValue().getAge());
}
You can use:
- Map.entrySet() (as mentioned by org.life.java) or,
- Map.keySet() as in this example (based on your sampled code)
Example:
Map<String, Person> personMap = ..... //assuming it's not null
Iterator<String> strIter = personMap.keySet().iterator();
synchronized (strIter) {
while (strIter.hasNext()) {
String key = strIter.next();
Person person = personMap.get(key);
String a = key;
String b = person.getName();
String c = person.getAge().toString();
System.out.println(String.format("Key : %s Name : %s Age : %s", a, b, c));
}
}
That is usually solved with reflection:
for (Field f : getClass().getDeclaredFields()) {
String name = f.getName();
String value = f.get(this);
}
However, for writing to / reading from XML, you probably want to use JAXB rather than reinventing the wheel.
Use Jackson:
https://github.com/FasterXML/jackson-dataformat-xml
Serialization is done very similar to JSON serialization: all that needs to change is ObjectMapper instance to use:
// Important: create XmlMapper; it will use proper factories, workarounds
ObjectMapper xmlMapper = new XmlMapper();
String xml = xmlMapper.writeValue(new Simple());
and with POJO like:
public class Simple {
public int x = 1;
public int y = 2;
}
you would get something like:
<Simple>
<x>1</x>
<y>2</y>
</Simple>
(except that by default output is not indented: you can enabled indentation using standard Jackson mechanisms)
Deserializing POJOs from XML Similar to serialization, deserialization is not very different from JSON deserialization:
ObjectMapper xmlMapper = new XmlMapper();
Simple value = xmlMapper
.readValue("<Simple><x>1</x><y>2</y></Simple>", Simple.class);
P.S. You can also use reflection for that and iterate via all declared fields using Class.getDeclaredFields(). But from my experience one rarely has to do that. There is a lot of 3rd party open-source libraries for different purposes and usually it's a better solution just to use them (e.g. Jackson in this particular case)
There is no linguistic support to do what you're asking for.
You can reflectively access the members of a type at run-time using reflection (e.g. with Class.getDeclaredFields() to get an array of Field), but depending on what you're trying to do, this may not be the best solution.
See also
- Java Tutorials: Reflection API / Advanced Language Topics: Reflection
Related questions
- What is reflection, and why is it useful?
- Java Reflection: Why is it so bad?
- How could Reflection not lead to code smells?
- Dumping a java object’s properties
Example
Here's a simple example to show only some of what reflection is capable of doing.
import java.lang.reflect.*;
public class DumpFields {
public static void main(String[] args) {
inspect(String.class);
}
static <T> void inspect(Class<T> klazz) {
Field[] fields = klazz.getDeclaredFields();
System.out.printf("%d fields:%n", fields.length);
for (Field field : fields) {
System.out.printf("%s %s %s%n",
Modifier.toString(field.getModifiers()),
field.getType().getSimpleName(),
field.getName()
);
}
}
}
The above snippet uses reflection to inspect all the declared fields of class String; it produces the following output:
7 fields:
private final char[] value
private final int offset
private final int count
private int hash
private static final long serialVersionUID
private static final ObjectStreamField[] serialPersistentFields
public static final Comparator CASE_INSENSITIVE_ORDER
Effective Java 2nd Edition, Item 53: Prefer interfaces to reflection
These are excerpts from the book:
Given a
Classobject, you can obtainConstructor,Method, andFieldinstances representing the constructors, methods and fields of the class. [They] let you manipulate their underlying counterparts reflectively. This power, however, comes at a price:
- You lose all the benefits of compile-time checking.
- The code required to perform reflective access is clumsy and verbose.
- Performance suffers.
As a rule, objects should not be accessed reflectively in normal applications at runtime.
There are a few sophisticated applications that require reflection. Examples include [...omitted on purpose...] If you have any doubts as to whether your application falls into one of these categories, it probably doesn't.
Accessing the fields directly is not really good style in java. I would suggest creating getter and setter methods for the fields of your bean and then using then Introspector and BeanInfo classes from the java.beans package.
MyBean bean = new MyBean();
BeanInfo beanInfo = Introspector.getBeanInfo(MyBean.class);
for (PropertyDescriptor propertyDesc : beanInfo.getPropertyDescriptors()) {
String propertyName = propertyDesc.getName();
Object value = propertyDesc.getReadMethod().invoke(bean);
}