Is there a way in Java to iterate through the attributes of an object? Just like this:
class SomeClass {
private Object field_1;
private Object field_2;
...
private Object field_n;
// methods here
}
where o.field(i) refers to o.field_i?
Maybe I misunderstood you question but if you want to manipulate JSON and Java objects you should consider using library like Genson or Jackson.
If you really want to inspect your class' attributes (which you should not really be considered because it is not really clean coding) you can consider reflection as indicated by Andremoniy
EDIT :
I'm sorry, as Vogel612 said I'll explain.
After reading the post comments, you seems to receive message on REST WebServices in JSON that is then converted to Java Object.
Correct me if I'm wrong but I think you want want to manipulate you Java object and obtain JSON or the other way round without coding everything by hand.
If it is what you need, you can consider the library I cited earlier and I would add Gson from Google. These libraies provide several method to convert automatically Java object to JSON and JSON to Java object without laborious conversion coding.
Of course you can, but it is not recommended, avoid at all cost if possible.
This code :
import java.lang.reflect.Field;
public class JavaApplication24 {
public Integer x;
public Integer y;
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
JavaApplication24 app = new JavaApplication24();
app.x = 10;
app.y = 20;
for (Field f : app.getClass().getDeclaredFields()) {
System.out.println(f.getName());
System.out.println(f.getType());
System.out.println(f.toGenericString());
System.out.println(f.get(app));
}
}
}
Have this output
x
class java.lang.Integer
public java.lang.Integer javaapplication24.JavaApplication24.x
10
y
class java.lang.Integer
public java.lang.Integer javaapplication24.JavaApplication24.y
20
Google reflection for more info.
You can use Apache commons BeanUtils to get all properties and their values.
Please refer describe() from PropertyUtils or PropertyBeanUtils class.
http://commons.apache.org/proper/commons-beanutils/javadocs/v1.9.2/apidocs/org/apache/commons/beanutils/PropertyUtils.html#describe(java.lang.Object)
E.g.
TestBean bean = new TestBean();
bean.setId(1);
bean.setName("test");
bean.setLastAccessed(new Date());
System.out.println(PropertyUtils.describe(bean));
Sure, you can via reflection. But it is not really efficient way for dealing with object's fields:
public static Object getFieldValue(SomeClass someClass, int i ) {
try {
Field declaredField = SomeClass.class.getDeclaredField("field_" + i);
declaredField.setAccessible(true);
Object value = declaredField.get(someClass);
declaredField.setAccessible(false);
return value;
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
Related
I have a list called itemsData of object of class EtcStruct, but the class can differ depending on the file i want to use (the class is full of variables setters and getters):
ObservableList<EtcStruct> itemsData = FXCollections.observableArrayList();
Im passing it to the method thats supposed to work for any object type i choose and run invoked method from the file.
public static void parseToFile(ObservableList itemsData){
EtcStruct itemObject = (EtcStruct) itemsData.get(0);
System.out.print((int)reflectedmethod.invoke(itemObject);
}
Code above works , but what i want to achieve is make the method work without editing it's object type to make it more flexible for whatever structclass i plan to use.
I tried something with passing Struct Class name and .getClass() it returns the original type but i dont know what to do with it to make the new object of itemsData original type and cast the itemsData object.
public static void parseToFile(ObservableList itemsData,Class c){
Object itemObject = c.newInstance();
Object newobject = curClass.newInstance();
newobject = c.cast(itemsList.get(0));
}
Above seemed dumb to me and obviously didnt work.
After reading your comment I understand better why one would use reflection in your case. A GUI builder/editor is an example where reflection is used to provide an interface to set/get the values of components. Still, IMHO, reflection isn't a tool you would design for when you own the classes and are the primary designer. If possible you should strive for something more like this:
interface Parsable {
default int parse() {
System.out.println("Here I do something basic");
return 0;
}
}
class BasicStruct implements Parsable { }
class EtcStruct implements Parsable {
#Override
public int parse() {
System.out.println("Here I do something specific to an EtcStruct");
return 1;
}
}
// If some structs have a parent-child relationship
// you can alternatively `extend EtcStruct` for example.
class OtherStruct extends EtcStruct {
#Override
public int parse() {
super.parse();
System.out.println("Here I do something specific to an OtherStruct");
return 2;
}
}
void parseToFile(Parsable parsable) {
System.out.println(parsable.parse());
}
// If you use a generic with a specific class you don't
// have to guess or care which kind it is!
void parseToFile(ObservableList<Parsable> parsables) {
for (Parsable p : parsables) {
parseToFile(p);
}
}
public static void main(String[] args) {
ObservableList<Parsable> parsables = FXCollections.observableArrayList();
parsables.add(new BasicStruct());
parsables.add(new EtcStruct());
parsables.add(new OtherStruct());
parseToFile(parsables);
}
Output:
Here I do something basic
0
Here I do something specific to an EtcStruct
1
Here I do something specific to an EtcStruct
Here I do something specific to an OtherStruct
2
Of course, this is just an example that needs to be altered to meet your needs.
But what I still don't get is if you're able to parse from a file why you can't parse to one. Nonetheless, I slapped some code together to show you how I might parse an object to a file, manually, when dealing with Objects only.
The idea is to satisfy a bean-like contract. That is, each structure should provide a parameter-less constructor, all fields you want managed by reflection will follow Java naming convention and will have both a public setter and getter.
Don't get caught up in the file writing; that will be determined by your needs. Just notice that by following this convention I can treat any Object as a parsable structure. A less refined version here for reference:
public void parseToFile(Object object) throws IOException, InvocationTargetException, IllegalAccessException {
fos = new FileOutputStream("example" + object.getClass().getSimpleName());
List<Method> getters = Arrays.stream(object.getClass().getMethods())
.filter(method -> method.getName().startsWith("get") && !method.getName().endsWith("Class"))
.collect(Collectors.toList());
for (Method getter : getters) {
String methodName = getter.getName();
String key = String.valueOf(Character.toLowerCase(methodName.charAt(3))) +
methodName.substring(4, methodName.length());
fos.write((key + " : " + String.valueOf(getter.invoke(object)) + "\n").getBytes());
}
fos.close();
}
I think that you can just still use Generics to keep static objects typing. Try to parametrize your function parseToFile. Here is an example:
public static void parseToFile(ObservableList<EtcStruct> itemsData){
EtcStruct itemObject = itemsData.get(0);
System.out.print((int)reflectedmethod.invoke(itemObject);
}
I am creating a store for user preferences, and there are a fixed number of preferences that users can set values for. The names of the preferences (settings) are stored as an Enum:
public enum UserSettingName {
FOO,
BAR,
ETC
}
What I would like to be able to do is store a value type with the name so that the service will store the user's value with the correct Java type. For example, FOO might be a Long, and BAR might be a String. Up until now, we were storing all values as Strings, and then manually casting the values into the appropriate Java type. This has lead to try/catch blocks everywhere, when it makes more sense to have only one try/catch in the service. I understand that Enums cannot have generic types, so I have been playing around with:
public enum UserSettingName {
FOO(Long.class),
BAR(String.class),
ETC(Baz.class)
private Class type;
private UserSettingName(Class type) {
this.type = type;
}
public Class getType() {
return this.type;
}
}
I have a generic UserSetting object that has public T getSettingValue() and public void setSettingValue(T value) methods that should return and set the value with the correct type. My problem comes from trying to specify that generic type T when I create or retrieve a setting because I can't do something like:
new UserSetting<UserSettingName.FOO.getType()>(UserSettingName.FOO, 123L)
Sorry if this isn't exactly clear, I can try to clarify if it's not understood.
Thanks!
UPDATE
Both the setting name and value are coming in from a Spring MVC REST call:
public ResponseEntity<String> save(#PathVariable Long userId, #PathVariable UserSettingName settingName, #RequestBody String settingValue)
So I used the Enum because Spring casts the incoming data automatically.
Firstly you have to step back and think about what you're trying to achieve, and use a standard pattern or language construct to achieve it.
It's not entirely clear what you're going after here but from your approach it almost certainly looks like you're reinventing something which could be done in a much more straightforward manner in Java. For example, if you really need to know and work with the runtime classes of objects, consider using the reflection API.
On a more practical level - what you're trying to do here isn't possible with generics. Generics are a compile-time language feature - they are useful for avoiding casting everything explicitly from Object and give you type-checking at compilation time. You simply cannot use generics in this way, i.e. setting T as some value UserSettingName.Foo.getType() which is only known at runtime.
Look how it done by netty:
http://netty.io/wiki/new-and-noteworthy.html#type-safe-channeloption
They done it by using typed constants:
http://grepcode.com/file/repo1.maven.org/maven2/io.netty/netty-all/4.0.0.Beta1/io/netty/channel/ChannelOption.java#ChannelOption
EDIT:
public interface ChannelConfig {
...
<T> boolean setOption(ChannelOption<T> option, T value);
...
}
public class ChannelOption<T> ...
public static final ChannelOption<Integer> SO_TIMEOUT =
new ChannelOption<Integer>("SO_TIMEOUT");
...
}
EDIT2: you can transform it like:
class Baz {}
class UserSettingName<T> {
public static final UserSettingName<Baz> ETC = new UserSettingName<Baz>();
}
class UserSetting {
public <T> UserSetting(UserSettingName<T> name, T param) {
}
}
public class Test {
public static void main(String[] args) {
new UserSetting(UserSettingName.ETC, new Baz());
}
}
Enums are not the answer here. If you find yourself repeating code everywhere you could just create a utility class and encapsulate all the try/catch logic there. That would cut down on your code redundancy without majorly impacting your current code.
public class Util
{
public static MyObject getObjectFromString(String s)
{
try
{
return (MyObject)s;
}
catch(Exception e)
{
return null;
}
}
}
Then use as follows:
MyObject myObj = Util.getObjectFromString(string);
I am trying to get a list of objects from the Database based on a target object through reflection.
I don't have much experience with reflection so this doesn't work.
Is it even possible to achieve my goal?
public static List<Object> getObjectsFromDataBase(Object targetObj) {
....................
ResultSet rs = stat.executeQuery(queryToExecute);
while (rs.next()) {
Object obj = new Object();
for (Field property : targetObj.getClass().getFields()) {
property.set(obj, rs.getString(property.getName()));
}
objListToReturn.add(obj);
}
.....................
return objListToReturn;
}
If the fields in the target object's class are not public they won't show up in getFields(). Try this:
import java.lang.reflect.Field;
public class Test
{
public static class A
{
public String field1;
public String field2;
}
public static void main(String[] args) throws Exception
{
A a = new A();
Object b = a;
for (Field f : b.getClass().getFields())
{
System.out.println(f.getName());
}
}
}
If you remove public, getFields() returns an empty array.
The short answer is yes, this is possible, but not with the code you provided. This concept is called Object Relational Mapping and things like Hibernate or XStream do this for you. If you're just learning about reflection that's great too. You'll probably need a way to map the fields to the properties of the object, whether that's done with convention (matched names), straight code, annotations, or a mapping input file is up to you.
I can see two problems:
You are creating obj as type Object. the first argument of Field.set() needs to be the same type (or a subtype) as the class the containing the field. You need to use reflection to create an object of the same type as targetObj, by using obj = targetObj.getClass().newInstance() (assuming a default constructor is available)
Also your problem might be that the getFields() method only returns the public fields of the class.
targetObj.getClass().getFields()
If you want to get all the fields of the class, you will need to use the getDeclaredFields() method.
I have a poorly designed class in a 3rd-party JAR and I need to access one of its private fields. For example,
why should I need to choose private field is it necessary?
class IWasDesignedPoorly {
private Hashtable stuffIWant;
}
IWasDesignedPoorly obj = ...;
How can I use reflection to get the value of stuffIWant?
In order to access private fields, you need to get them from the class's declared fields and then make them accessible:
Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException
EDIT: as has been commented by aperkins, both accessing the field, setting it as accessible and retrieving the value can throw Exceptions, although the only checked exceptions you need to be mindful of are commented above.
The NoSuchFieldException would be thrown if you asked for a field by a name which did not correspond to a declared field.
obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException
The IllegalAccessException would be thrown if the field was not accessible (for example, if it is private and has not been made accessible via missing out the f.setAccessible(true) line.
The RuntimeExceptions which may be thrown are either SecurityExceptions (if the JVM's SecurityManager will not allow you to change a field's accessibility), or IllegalArgumentExceptions, if you try and access the field on an object not of the field's class's type:
f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type
Try FieldUtils from Apache commons-lang3:
FieldUtils.readField(object, fieldName, true);
P.S. In my opinion, reflection is evil.
Reflection isn't the only way to resolve your issue (which is to access the private functionality/behaviour of a class/component)
An alternative solution is to extract the class from the .jar, decompile it using (say) Jode or Jad, change the field (or add an accessor), and recompile it against the original .jar. Then put the new .class ahead of the .jar in the classpath, or reinsert it in the .jar. (the jar utility allows you to extract and reinsert to an existing .jar)
As noted below, this resolves the wider issue of accessing/changing private state rather than simply accessing/changing a field.
This requires the .jar not to be signed, of course.
One other option that hasn't been mentioned yet: use Groovy. Groovy allows you to access private instance variables as a side effect of the design of the language. Whether or not you have a getter for the field, you can just use
def obj = new IWasDesignedPoorly()
def hashTable = obj.getStuffIWant()
Using the Reflection in Java you can access all the private/public fields and methods of one class to another .But as per the Oracle documentation in the section drawbacks they recommended that :
"Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform"
here is following code snapts to demonstrate basic concepts of Reflection
Reflection1.java
public class Reflection1{
private int i = 10;
public void methoda()
{
System.out.println("method1");
}
public void methodb()
{
System.out.println("method2");
}
public void methodc()
{
System.out.println("method3");
}
}
Reflection2.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflection2{
public static void main(String ar[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
Method[] mthd = Reflection1.class.getMethods(); // for axis the methods
Field[] fld = Reflection1.class.getDeclaredFields(); // for axis the fields
// Loop for get all the methods in class
for(Method mthd1:mthd)
{
System.out.println("method :"+mthd1.getName());
System.out.println("parametes :"+mthd1.getReturnType());
}
// Loop for get all the Field in class
for(Field fld1:fld)
{
fld1.setAccessible(true);
System.out.println("field :"+fld1.getName());
System.out.println("type :"+fld1.getType());
System.out.println("value :"+fld1.getInt(new Reflaction1()));
}
}
}
Hope it will help.
As oxbow_lakes mentions, you can use reflection to get around the access restrictions (assuming your SecurityManager will let you).
That said, if this class is so badly designed that it makes you resort to such hackery, maybe you should look for an alternative. Sure this little hack might be saving you a few hours now, but how much will it cost you down the road?
Java 9 introduced Variable Handles. You can access a private field of a class using them.
The code for your example will look like following:
var lookup = MethodHandles.lookup();
var handle = MethodHandles
.privateLookupIn(IWasDesignedPoorly.class, lookup)
.findVarHandle(IWasDesignedPoorly.class, "stuffIWant", Hashtable.class);
var value = handle.get(obj);
It is also advisable to use Lookup and VarHandle objects as static final fields.
Use the Soot Java Optimization framework to directly modify the bytecode.
http://www.sable.mcgill.ca/soot/
Soot is completely written in Java and works with new Java versions.
If using Spring:
In a testing context, ReflectionTestUtils provides some handy tools that can help out here with minimal effort. It's described as being "for use in unit and integration testing scenarios".
In a non-testing context, there is also a similar class named ReflectionUtils but this is described as "Only intended for internal use" - see this answer for a good interpretation of what this means.
To address the example in the original post:
Hashtable iWantThis = (Hashtable)ReflectionTestUtils.getField(obj, "stuffIWant");
You need to do the following:
private static Field getField(Class<?> cls, String fieldName) {
for (Class<?> c = cls; c != null; c = c.getSuperclass()) {
try {
final Field field = c.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (final NoSuchFieldException e) {
// Try parent
} catch (Exception e) {
throw new IllegalArgumentException(
"Cannot access field " + cls.getName() + "." + fieldName, e);
}
}
throw new IllegalArgumentException(
"Cannot find field " + cls.getName() + "." + fieldName);
}
You can use jOOR for that.
class Foo {
private final String value = "ABC";
}
class Bar {
private final Foo foo = new Foo();
public String value() {
return org.joor.Reflect
.on(this.foo)
.field("value")
.get();
}
}
class BarTest {
#Test
void accessPrivateField() {
Assertions.assertEquals(new Bar().value(), "ABC");
}
}
Just an additional note about reflection: I have observed in some special cases, when several classes with the same name exist in different packages, that reflection as used in the top answer may fail to pick the correct class from the object. So if you know what is the package.class of the object, then it's better to access its private field values as follows:
org.deeplearning4j.nn.layers.BaseOutputLayer ll = (org.deeplearning4j.nn.layers.BaseOutputLayer) model.getLayer(0);
Field f = Class.forName("org.deeplearning4j.nn.layers.BaseOutputLayer").getDeclaredField("solver");
f.setAccessible(true);
Solver s = (Solver) f.get(ll);
(This is the example class that was not working for me)
It is quite easy with the tool XrayInterface. Just define the missing getters/setters, e.g.
interface BetterDesigned {
Hashtable getStuffIWant(); //is mapped by convention to stuffIWant
}
and xray your poor designed project:
IWasDesignedPoorly obj = new IWasDesignedPoorly();
BetterDesigned better = ...;
System.out.println(better.getStuffIWant());
Internally this relies on reflection.
Try to go around the problem for the case, the calass of which you want to set/get data is one of your own classes.
Just create a public setter(Field f, Object value) and public Object getter(Field f) for that. You can even do some securoty check on your own inside theses member functions. E.g. for the setter:
class myClassName {
private String aString;
public set(Field field, Object value) {
// (A) do some checkings here for security
// (B) set the value
field.set(this, value);
}
}
Of course, now you have to find out the java.lang.reflect.Field for sString prior to setting of field value.
I do use this technique in a generic ResultSet-to-and-from-model-mapper.
Newbie Java question. Say I have:
public class Car{
...
}
public class Truck extends Car{
...
}
Suppose I already have a Car object, how do I create a new Truck object from this Car object, so that all the values of the Car object is copied into my new Truck object?
Ideally I could do something like this:
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck(c);
/* would like t to have all of c's values */
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Yes, just add a constructor to Truck. You will probably want to add a constructor to Car also, though not necessarily public:
public class Car {
protected Car(Car orig) {
...
}
public class Truck extends Car {
public Truck(Car orig) {
super(orig);
}
...
}
As a rule it's generally best to make classes either leaf (and you might want to mark those final) or abstract.
It looks as if you want a Car object, and then have the same instance turn into a Truck. A better way of doing this is to delegate behaviour to another object within Car (Vehicle). So:
public final class Vehicle {
private VehicleBehaviour behaviour = VehicleBehaviour.CAR;
public void becomeTruck() {
this.behaviour = VehicleBehaviour.TRUCK;
}
...
}
If you implement Cloneable then you can "automatically" copy an object to a instance of the same class. However there are a number of problems with that, including having to copy each field of mutable objects which is error-prone and prohibits the use of final.
If you are using Spring in your project you may use ReflectionUtils.
Yes, you have to do this manually. You'll also need to decide how "deeply" to copy things. For instance, suppose the Car has a collection of tyres - you could do a shallow copy of the collection (such that if the original object changes the contents of its collection, the new object would see the change too) or you could do a deep copy which created a new collection.
(This is where immutable types like String often come in handy - there's no need to clone them; you can just copy the reference and know that the contents of the object won't change.)
Would I have to write my own copy constructor? This would have to be
updated everytime Car gets a new field...
Not at all!
Try this way:
public class Car{
...
}
public class Truck extends Car{
...
public Truck(Car car){
copyFields(car, this);
}
}
public static void copyFields(Object source, Object target) {
Field[] fieldsSource = source.getClass().getFields();
Field[] fieldsTarget = target.getClass().getFields();
for (Field fieldTarget : fieldsTarget)
{
for (Field fieldSource : fieldsSource)
{
if (fieldTarget.getName().equals(fieldSource.getName()))
{
try
{
fieldTarget.set(target, fieldSource.get(source));
}
catch (SecurityException e)
{
}
catch (IllegalArgumentException e)
{
}
catch (IllegalAccessException e)
{
}
break;
}
}
}
}
you can use reflection i do it and work fine for me:
public Child(Parent parent){
for (Method getMethod : parent.getClass().getMethods()) {
if (getMethod.getName().startsWith("get")) {
try {
Method setMethod = this.getClass().getMethod(getMethod.getName().replace("get", "set"), getMethod.getReturnType());
setMethod.invoke(this, getMethod.invoke(parent, (Object[]) null));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//not found set
}
}
}
}
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Essentially, yes - you can't just convert an object in Java.
Fortunately you don't have to write all the code yourself - look into commons-beanutils, specifically methods like cloneBean. This has the added advantage that you don't have to update it every time it gets a new field!
You could always use a mapping Framework such as Dozer. By default (without further configuration), it maps all fields of the same name from one object to another using the getter and setter methods.
Dependency:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.5.1</version>
</dependency>
Code:
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
// ...
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck();
Mapper mapper = new DozerBeanMapper();
mapper.map(c, t);
/* would like t to have all of c's values */
You will need a copy constructor, but your copy constructor can use reflection to find the common fields between the two objects, get their values from the "prototype" object, and set them on the child object.
You could use the reflection API to loop through each of the Car fields and assign the value to the equivalent Truck fields. This can be done within truck. Further it is the only way to access the private fields of Car - at least in an automatic sense, providing that a security manager is not in place and restricting access to private field.
The solutions presented above have limitations you should be aware of. Here's a short summary of algorithms for copying fields from one class to another.
Tom Hawtin: Use this if your superclass has a copy constructor. If it does not you will need a different solution.
Christian: Use this if the superclass does not extend any other class. This method does not copy fields recursively upwards.
Sean Patrick Floyd: This is a generic solution for copying all fields recursively upwards. Be sure to read #jett's comment that a single line must be added to prevent an endless loop.
I reproduce Sean Patrick Floyd's analyze function with the missing statement:
private static Map<String, Field> analyze(Object object) {
if (object == null) throw new NullPointerException();
Map<String, Field> map = new TreeMap<String, Field>();
Class<?> current = object.getClass();
while (current != Object.class) {
Field[] declaredFields = current.getDeclaredFields();
for (Field field : declaredFields) {
if (!Modifier.isStatic(field.getModifiers())) {
if (!map.containsKey(field.getName())) {
map.put(field.getName(), field);
}
}
}
current = current.getSuperclass(); /* The missing statement */
}
return map;
}
I know this is an OLD question, but I hate to leave out dated answers when things have improved.
Using JSON is much easier. Convert it to JSON and back again as child.
Here is an Android Kotlin Example.
val gson = Gson()
val childClass = gson.fromJson(
gson.toJson(parentObject),
object: TypeToken<ChildObject>(){}.type
) as ChildObject
I think in Java it would be basically.
Gson gson = new Gson()
ChildObject child = (ChildObject) gson.fromJson(
gson.toJson(parentObject),
TypeToken<ChildObject>(){}.getType()
)
And you're done, no messiness, just simple json in, json out.
If you don't have gson, I'm sure you have other json options available to you.
It's a WHOLE lot cleaner and faster than doing reflection and all that craziness.