How to use string to compare with field names in java? - java

I have a class named MyClass. It has many fields of type MyField. How do I return a reference to a particular field whose name matches a String's value?
public class MyClass{
public MyField field1;
public MyField field2;
public MyField field3;
public MyField whichField(String nameOfField){
//e.g. String = "field3", then return field3
//of course I can do if else, but it will be tedious If I have long list of MyField fields, can I iterate over all field names, and return whose name matches?
}
}
edit
I tried reflection from the answers below, I create a temp placeholder, and I wish to reutrn it but,
MyField temp = MyClass.class.getDeclaredField(whichFieldString);
doesnt work, I get type mismatch, cant convert error
How do I cast this?
How do I return this field?

As an alternative:
If all fields are of the same type and are accessed by their field name (most of the time) you could avoid the hassle and brittleness of using reflection by utilizing a Map.
The map associates a key (in your case the "field name") with a value. Instead of an arbitrary number of fields, MyClass would look like:
public class MyClass {
private final Map<String, MyField> fields = new HashMap<>();
/* code to initially fill the map */
public MyField whichField(String fieldName) {
return fields.get(fieldName);
}
}

You can do this with reflection. Class A has the fields we want to search through:
public class A {
private String field1;
private String field2;
private String field3;
}
And B shows how to iterate over the fields declared in A, matching on a particular field name:
public class B {
public B() {
Field field = findFieldByName("field1");
System.out.println(field);
}
private Field findFieldByName(String name) {
Field[] fields = A.class.getDeclaredFields();
for(Field f : fields) {
if(f.getName().equals(name)) {
return f;
}
}
return null;
}
public static void main(String[] args) {
new B();
}
}

You'll have to use reflection:
import java.lang.reflect.Field;
public class MyClass {
public MyField field1;
public MyField field2;
public MyField field3;
public MyField whichField(String nameOfField) {
MyField fieldName = null;
Field[] fields = MyClass.class.getDeclaredFields();
for (Field field : fields) {
if (field.getName().equals(nameOfField)) {
// Do whatever you want to do
}
}
return null;
}
}
class MyField {
}

You may want to use a collection, e.g. Map<String, MyField>.

You can do it easily with reflection
Class<MyClass> clazz = MyClass.class;
Field requieredField = clazz.getDeclaredField("myFielldName");
EDIT
This solution is pertinent is the number of fields is fixed. As it was mentioned in comments and answers, if you want to store a dynamic number of values, then a Map (or a Collection if you only need to enumerate the values) is much more suitable.

Related

Output a field to multiple json fields

Is there a way using, Jackson annotations, to have a have given field serialised to 2 json fields.
Like the reverse of #JsonAlias which deserialises multiple json field to the one field.
Eg
class Foo {
#SomeAnnotation("field2")
String field1;
}
serialising as:
{
"field1" : "xyz",
"field2" : "xyz"
}
Is there a something like #SomeAnnotation?
——
Note: This is not a “should” I do this (it’s an imposed requirement), it’s a “how” I do this (elegantly).
A simple solution to this may be to just add two getters for field1:
class Foo {
private String field1 = "blah";
public String getField1() {
return field1;
}
public String getField2() {
return field1;
}
}
Jackson will create a field for each getter, following the javabeans naming convention:
{"field1":"blah","field2":"blah"}
An alternative to this may be #com.fasterxml.jackson.annotation.JsonAnyGetter, which can afford you even more flexibility:
class Foo {
private String field1 = "blah";
public String getField1() {
return field1;
}
#JsonAnyGetter
public Map<String, Object> getAny() {
Map<String, Object> m = new HashMap<>();
m.put("field2", this.field1);
m.put("field3", this.field1.toUpperCase());
return m;
}
}
Producing:
{"field1":"blah","field3":"BLAH","field2":"blah"}

Java iterate over class fields to create other class

I have a class like this:
public class Example {
private String a;
private Integer b;
private Boolean c;
private List<AnotherClass> d;
}
and I want to convert it to something like this:
[
{
name: "a",
value: "a value"
},
{
name: "b",
value: "1",
},
{
name: "c",
value: "true",
}
]
So, I create a class like this:
public class Test {
private String name;
private String value;
}
I want to have a method to iterate through the Example class so it will produce the Test class without including d attribute. How to achieve that?
This is something you can do easily with reflection. In the example below, I renamed class Test to Property because it represents a key-value pair. If you are happy with using whatever toString() returns as the value for a field, then the solution is pretty simple:
public class Property {
private final String name;
private final String value;
public Property(String name, String value) {
this.name = name;
this.value = value;
}
public static List<Property> toProperties(Object object, String... fieldNames)
throws ReflectiveOperationException
{
ArrayList<Property> properties = new ArrayList<>();
for( String fieldName : fieldNames ) {
Field field = object.getClass().getDeclaredField(fieldName);
properties.add(new Property(fieldName, field.get(object).toString()));
}
return properties;
}
public String toString() {
return String.format("%s: \"%s\"", name, value);
}
}
This sample requires you to specify the names of the desired fields explicitly, for example:
List<Property> properties = Property.toProperties(myExample, "a", "b", "c");
If you'd rather have the fields be auto-detected based on some criterion (for example all primitive and String-typed fields, then you could add this logic within toProperties and get rid of the varargs.
you would need to have some appropriate getters in class Example, and a proper constructor in class Test to initialize the object instance variables like
public Test (String name, int value) {
this.name = name;
this.value = value'
}
Then for each instance of class Example - lets say you have multiple of those in an array or list - you could iterate over them, retrieve the values you want via the getter methods, and initialize one Test object for each one, eg
List<Test> yourListOfTestInstances = new ArrayList<>();
for (Example exampleObject : yourExampleObjectsListOrArray) {
yourListOfTestInstances.add(new Test(exampleObject.getA() , exampleObject.getB()));
}
Then for each created Test instance inside your ArrayList, you could easily build your JSON as needed (even though I do not fully understand why you even need at all this intermediate Test class to do that)

Java self-reflection

It's rather strange, but I want to call self method.
This is my abstract class
public abstract class AbstractMapper {
public AbstractMapper(Map<String, String> map) {
Field[] fields = this.getClass().getDeclaredFields();
for (Field field: fields) {
if (field.getAnnotation(Column.class) != null) {
String fName = field.getName();
String rsName = field.getAnnotation(Column.class).name();
StringBuilder sb = new StringBuilder("set")
.append(Character.toUpperCase(fName.charAt(0)))
.append(fName.substring(1));
String mName = sb.toString();
// this.invoke(mName, map.get(fName)); <-- What should I put this here?
}
}
}
public Result getCalculatedValues() {
return xxxx;
}
}
And this is my class
public class NewMachine extends AbstractMapper{
#column(name = machine)
private String machine;
#column(name = temperature)
private Double temperature;
// normal get/set methods
}
Now, my goal is that AbstractMapper constructor iterates through all fields with columns, and invoke all of its respective setters.
in this case, I can pass something like
Map<String, String> map = SomeClass.SomeMethod();
NewMachine m = new NewMachine(map);
Result r = m.getCalculatedValues();
Thank you for helping.
Try getClass().getMethod( mName, field.getType() ).invoke(this, map.get(fName) ) (and handle any possible exceptions ofc).
Additionally keep the JavaDoc on getDeclaredFields() in mind:
Returns an array of {#code Field} objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields.
If you have a hierarchy you'd have to get the fields of the super classes as well.

Read static field of interface via reflection

I've got an interface:
public interface Interface {
public static final String FIELD1 = "BAR";
public static final String FIELD2 = "FOO";
.........
}
I'm trying to read the field name via reflection using this code:
Field[] fields = Interface.class.getFields();
for (Field f : fields) {
............
}
The problem is that the array has always length zero. Why?
Edit: I'm using proguard and I think the problem is related with interface obfuscation.
I am running the same code as you have provided and able to print the name of the fields from the interface.
import java.lang.reflect.Field;
public class Prop {
public static void main(String[] args)
{
Field[] fields = Interface.class.getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
}
}
interface Interface {
public static final String FIELD1 = "BAR";
public static final String FIELD2 = "FOO";
}
Ouput:
FIELD1
FIELD2
Simply use:
Field[] fields = Interface.class.getDeclaredFields();
Instead of :
Field[] fields = Interface.class.getFields();
It worked fine for me!

Java Reflection - listing properties (getters & setters) of a class

public class foo
{
private String _name;
private String _bar;
public String getName() {
return _name;
}
public void setName(String name) {
_name = name;
}
public String getBar() {
return _bar;
}
public void setBarn(String bar) {
_bar = bar;
}
}
If I have the above class can I use reflection to list the properties defined by the getters and setters? I've tried the method below but it doesn't work, Field[] fields is left empty. I know I can do this in .Net but Java is a very different animal. Am I barking up the wrong tree altogether?
private HashMap<String, String> getHashMap(Object obj) {
HashMap<String, String> map = new HashMap<String, String>();
Class<?> cls = obj.getClass();
Field fields[] = cls.getFields();
for(Field f : fields) {
String name = f.getName();
String value = f.get(obj).toString();
map.put(name, value);
}
return map;
}
Also setters and getters maybe evil, should I just drop this?
Maybe use cls.getDeclaredFields instead ? (And f.setAccessible(true) before get private field).
If you want getter and setter you have to get method by getDeclaredMethods. Then I suggest using BeanUtils instead of writing your own reflection logic :) (IMHO less convenient is java.beans.Introspector).
Use the Introspector class. Obtain the BeanInfo and use getPropertyDescriptors() method. That should get you on the way.
You can do something like this:
List<Method> methods = Arrays.asList(getClass().getDeclaredMethods());
for (Method m : methods)
{
String name = m.getName();
if (name.startsWith("get") || name.startsWith("is"))
{
// Do something with the getter method
} else if (name.startsWith("set"))
{
// Do something with the setter method
}
}

Categories

Resources