Retrieving a value using Reflection

I'm trying to write a class that stores a list of field names, takes an object as a parameter, then builds a string based on the values contained within the field names stored in the array.

The class uses reflection so that I can pass any object to this method.

To keep things simple, I am only looking for the values from the primitive types (just the way the app turned out). But I cannot get the value from the field in the object that is passed. If I cast the type and print out the values, they show up properly. But I do not think that I am calling the proper method to read the value.

public class TSorter

{

private String fieldNames[] = null;

public TSorter(String names[]) { setFieldNames(names); }

public void setFieldNames(String names[])

{

fieldNames = new String[names.length];

for (int ndx=0; ndx < names.length; ndx++)

fieldNames[ndx] = names[ndx];

}

public String getKey(Object data)

{

StringBuffer key = new StringBuffer();

System.out.println("getKey: " + ((BinderObject)data).getBinderId() + ", " + ((BinderObject)data).getBinderDesc());

Class cl = data.getClass();

for (int ndx=0; ndx < fieldNames.length; ndx++)

{

System.out.println("Get field: " + fieldNames[ndx]);

try

{

Field field = cl.getDeclaredField(fieldNames[ndx]);

System.out.println("Type: " + field.getType().toString());

if (ndx > 0)

key.append("~");

// Get the value contained in the object

key.append(field.get(data).toString());

}

catch (NoSuchFieldException e) { }

catch (Exception e) { }

}

return key.toString();

}

Thanks in advance

Michael V. Peremsky

[1795 byte] By [mperemsky] at [2007-9-26 2:47:49]
# 1

To add a little more info.

Here is the BinderObject class

public class BinderObject implements Serializable

{

// Instance variables

private long binderId;

private String binderDesc;

public long getBinderId() { return this.binderId; }

public void setBinderId(long bid) { this.binderId = bid; }

public String getBinderDesc() { return this.binderDesc; }

public void setBinderDesc(String bdesc) { this.binderDesc = bdesc; }

Now if my Main funciton is as follows:

static public void main(String args[])

{

BinderObject b = new BinderObject();

b.setBinderId(555);

b.setBinderDesc("My Binder");

b.setOrgCode(777);

TSorter s = new TSorter(new String[] { "binderId" });

System.out.println("[" + s.getKey(b) + "]");

s.setFieldNames(new String[] { "binderId", "binderDesc" });

System.out.println("[" + s.getKey(b) + "]");

}

The 'getKey()' method will throw a NoSuchFieldException when it tried to read the 'binderId' field from the object. But this field is obviously defined.

Can anyone see what I am missing?

mperemsky at 2007-6-29 10:32:40 > top of Java-index,Core,Core APIs...
# 2
Correction, it throws an IllegalAccessException.
mperemsky at 2007-6-29 10:32:40 > top of Java-index,Core,Core APIs...
# 3

I copied your code and ran it and it worked. See?

getKey: 555, My Binder

Get field: binderId

Type: long

[]

getKey: 555, My Binder

Get field: binderId

Type: long

Get field: binderDesc

Type: class java.lang.String

[~]

I'm running the latest Java 1.3, so maybe it's a bug.

Otherwise, you might consider changing the access from private to public, see if that helps.

etscenterspan at 2007-6-29 10:32:40 > top of Java-index,Core,Core APIs...
# 4

Here is the complete code (with exceptions being printed out). It is throwing an IllegalAccessException, which I was not actually expecting.

I do not know why it is throwing this as neither class is declared to be in a package, both classes are public and both contained in the same directory.

You will note when running this that it throws the exception on the line:

System.out.println("1: " + field.get(data));

import java.lang.reflect.Field;

public class TSorter

{

private String fieldNames[] = null;

public TSorter(String names[])

{

setFieldNames(names);

}

/**

* This method will save the field names that are to be used as the key.

*/

public void setFieldNames(String names[])

{

fieldNames = new String[names.length];

for (int ndx=0; ndx < names.length; ndx++)

fieldNames[ndx] = names[ndx];

}

/**

* This method will return the key that is used for the passed object.

* The key will be generaed based on the field names stored in the

* fieldNames array.

*/

public String getKey(Object data)

{

StringBuffer key = new StringBuffer();

System.out.println("\ngetKey: " + ((BinderObject)data).getBinderId() + ", " + ((BinderObject)data).getBinderDesc());

Class cl = data.getClass();

for (int ndx=0; ndx < fieldNames.length; ndx++)

{

System.out.println("Get field: " + fieldNames[ndx]);

try

{

Field field = cl.getDeclaredField(fieldNames[ndx]);

System.out.println("Type: " + field.getType().toString());

System.out.println("1: " + field.get(data));

System.out.println("2: " + (Integer)field.get(data));

if (ndx > 0)

key.append("~");

// Get the value contained in the object

key.append(field.get(data).toString());

}

catch (NoSuchFieldException nsf){ System.out.println("No Such Field Exception: " + fieldNames[0]);}

catch (IllegalArgumentException iarg) { System.out.println("Illegal Arguement Exception: " + fieldNames[0]);}

catch (IllegalAccessException iacc){ System.out.println("Illegal Access Exception: " + fieldNames[0]);}

catch (Exception e) { }

}

return key.toString();

}

static public void main(String args[])

{

BinderObject b = new BinderObject();

b.setBinderId(555);

b.setBinderDesc("My Binder");

b.setOrgCode(777);

TSorter s = new TSorter(new String[] { "binderId" });

System.out.println("[" + s.getKey(b) + "]");

s.setFieldNames(new String[] { "binderId", "binderDesc" });

System.out.println("[" + s.getKey(b) + "]");

}

}

mperemsky at 2007-6-29 10:32:40 > top of Java-index,Core,Core APIs...
# 5
If I'm not totally confused by your code, the fields you are trying to access are declared private. You can't get the values of private fields via reflection, that's an Illegal Access.
DrClap at 2007-6-29 10:32:40 > top of Java-index,Core,Core APIs...
# 6
Ack! You're right. Thanks
mperemsky at 2007-6-29 10:32:40 > top of Java-index,Core,Core APIs...
# 7

That what I said in my original reply ("Otherwise, you might consider changing the access from private to public, see if that helps.")

BUT! Note that it worked on my machine, where it was exactly as you had it - private. That's why I was wondering what version of Java you're using.

Anyway, hope it works now.

etscenterspan at 2007-6-29 10:32:40 > top of Java-index,Core,Core APIs...