Access enum name through reflection - java

I am trying to access the name of an enum through reflection (the name field of the Enum class) but I get a NoSuchFieldException.
See below a simple example: the program prints 5 for the Integer but throws an Exception for the enum.
Is there an elegant way to get the inspect method to work for enums?
public class Test {
static enum A {
A;
}
public static void main(String[] args) throws Exception {
Integer i = 5;
System.out.println(inspect(i, "value")); // prints 5, good
A a = A.A;
System.out.println(inspect(a, "name")); // Exception :-(
}
private static Object inspect(Object o, String fieldName) throws Exception {
Field f = o.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(o);
}
}

getField or getDeclaredField methods will only return positive results for fields declared in called class. They will not search for fields declared in superclasses. So, to get the refference for name field, you'll need to go deeper. Get the superclass reference (which in your case will be Enum class) and search for name field there.
o.getClass().getSuperclass().getDeclaredField(fieldName);

Related

Can I access the static variables of the 'Class' Object?

Having this method:
readAllTypes(Class clazz) {...}
Can I access the static variables of the class?
Yes. Just use Class.getDeclaredFields() (or Class.getDeclaredField(String)) as normal, and to get the values, use the Field.getXyz() methods, passing in null for the obj parameter.
Sample code:
import java.lang.reflect.Field;
class Foo {
public static int bar;
}
class Test {
public static void main(String[] args)
throws IllegalAccessException, NoSuchFieldException {
Field field = Foo.class.getDeclaredField("bar");
System.out.println(field.getInt(null)); // 0
Foo.bar = 10;
System.out.println(field.getInt(null)); // 10
}
}
You can find the field using clazz.getDeclaredFields(), which returns a Field[], or by directly getting the field by name, with clazz.getDeclaredField("myFieldName"). This may throw a NoSuchFieldException.
Once you've done that, you can get the value of the field with field.get(null) if the field represents an object, or with field.getInt(null), field.getDouble(null), etc. if it's a primitive. To check the type of the field, use the getType or getGenericType. These may throw an IllegalAccessException if they're not public, in which case you can use field.setAccessible(true) first. You can also set the fields in the same way if you just replace "get" with "set".

Android Java, How to get the value of class attribute?

I want to get the value a class attribute, But I am getting exception : java.lang.NoSuchFieldException
Person.class
public class Person {
public static final String name = "person name";
}
MainActivity.class
...
private void method() {
Class myClass = Person.class;
String name = myClass.getField("name");
}
...
I am getting a java.lang.NoSuchFieldException exception for the getField method.
I tried these solutions but with no avail ...
Change getField method to getDeclaredField
Surround the code by try/catch, and got another error (Incompatible types : java.lang.String and java.lang.reflect.Field)
Invalidate Android Studio caches and restart
I don't Know how to access this value, Any solutions or suggestions are welcomed.
Thanks in advance.
Change getField method to getDeclaredField
Surround the code by try/catch, and got another error (Incompatible
types : java.lang.String and java.lang.reflect.Field)
that because getDeclaredField will return object of type Field not String,
just change your code to this
Field field = myClass.getDeclaredField("name");
//do something with field
If you want to access the value of the field, you can use the get(...) method with a null argument - since it's a static field, it does not require any instance:
private void method() {
Class myClass = Person.class;
Field field = myClass.getField("name");
String name = field.get(null);
Log.d("Test", "field value: " + name);
}
In your case, it doesn't matter whether you use getField(...) or getDeclaredField(...). You would want to use the latter if you want to grab a field in its superclass or an interface implemented by your class.
For example, if Person were to extend from a class that has a field named sample, you would need to use getDeclaredField("sample") instead.
If your variable in the class "Person" is static:
(This is not the best solution in my opinion)Explanation: getField method returns a type "field" so you CAN NOT save into a variable from another type without a conversion.
YourField.get returns an object so you CAN NOT save into a variable from another type without a conversion.
try{
Class _person = Person.class;
Field field = _person.getField("name");
Object value = field.get(null);
String valueString = (String)value; /*The String you are looking for*/
}catch (Exception e) {
//TODO handle exception
}
If your variable in the class "Person" is static:
String valueString = Person.name /*The value you are looking for*/
If your variable isn't static but public:
IMPORTANT (If you have not set a default value to the variable): In this case the value will be an empty string because you are creating a new instance of your calss. You can set the "person name" in the constructor of your Person class another way you will get an empty string because the variable isn't static.
Person _person = new Person();
String personName = _person.name;
Since that's a constant you declared, access it directly with the class name as below,
String name = Person.name;
It's a static constant. Static means there is only one value at a time possible. Or say it like this: The class attribute 'name' is a class attribute, not an object attribute! The attribute belongs to the class!
So you don't need to create an instance of your Person class.
You just can use:
String name = Person.name;
Remember: this only works cause the name belongs to the class. And it does so, because you declared your name variable static.

Get a field's value

I want to get the value with which the field is being initialized.
Example:
class ClassA {
public String someString = "Merry Christmas";
}
class ClassB {
String anotherString = ClassA.class.getField("someString");
}
Is there any way to do this?
This would be possible if ClassA.string were static. In this case you would be able to get the value through reflection without the need to get a hold of an instance of ClassA inside of which someString is defined:
class ClassA {
public static String someString = "Merry Christmas";
}
...
Object s = ClassA.class.getField("someString").get(null);
Demo 1.
If the variable is not static, and you simply want to get its initial value, you could still do it, assuming that ClassA has a default constructor:
public static void demo(Class<?> cl) throws Exception {
Object s = cl.getField("someString").get(cl.newInstance());
System.out.println(s);
}
Demo 2.
You first have to create an instance o ClassA into ClassB:
ClassA a = new ClassA();
System.out.println(a.someString);
But according to the current format of your code, the best option would be declaring someString static: public static String someString = "Merry Christmas";. Then you can directly access this field from any other class of any package (as it's public):
System.out.println(ClassA.someString);
I think you do not fully understand what a (non-static) field means: it means the field has a specific value for each instance (object) of ClassA, so you cannot access the fields content, because there can be thousands, each with a different value.
There are several options:
A possible solution is to make the field static:
ClassA {
public static String someString = "Merry Christmas";
}
ClassB {
String anotherString = ClassA.someString;
}
Or as #toubou says, you can construct an object and access the field of that specific object. Note however that fields represent an object's state, and therefore can modify.

Using reflection get a static private hashmap in java

I'm trying to find a way to extract a HashMap from a private static field within another class via Java.
eg.
Inside FooClass there is a static field that looks like this:
private Map entityRenderMap;
Then in its construct it has:
entityRenderMap = new HashMap();
How do you get the values within entityRenderMap via Reflection in Java? I've tried this but get errors:
cl = RenderManager.class.getDeclaredField("entityRenderMap");
cl.setAccessible(true);
Object foo = cl.get(this.entityRenderMap);
Mod.log(cl.getName());
The error I get is:
java.lang.IllegalArgumentException: Can not set java.util.Map field RenderManager.entityRenderMap to java.util.HashMap
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(Unknown Source
First, your code doesn't match your explanation. Is it really a static field or is it not (your code says it's not)?
If it is static, you should pass null as argument to cl.get() (you don't need an instance to access static members).
However, I suspect that your field is actually not static, and your passing the wrong instance to cl.get(). The JavaDocs to Field.get() state it would throw an IllegalArgumentException in this case. You need to pass a RenderManager instance to this method. Your code looks like your passing a Map (the entityRenderMap).
And last, is this code inside your RenderManager class? I suspect this, because your accessing a field with this with the same name as the field you want to set. In this case, don't use reflection at all!
Are you certain it is a static field. The javadoc of the get method clearly states:
If the underlying field is a static field, the obj argument is ignored; it may be null.
Otherwise, the underlying field is an instance field. If the specified obj argument is null, the method throws a NullPointerException. If the specified object is not an instance of the class or interface declaring the underlying field, the method throws an IllegalArgumentException.
So with a static field you would not get the IllegalArgumentException since the parameter is ignored. Further, the code you posted shows it is not a static field but a regular field (since it lacks the word static, and its initialized in the constructor).
If you want to access the field of a certain instance A, you should pass that instance A to the Field#get method, and not the A.field as you are trying to do with your cl.get(this.entityRenderMap) call.
You can take a look at this tutorial for some examples
If the field is really static, you should pass null as an argument to cl.get().
If the field is not static, then you must pass the instance of FooClass which you want to get the field value from:
FooClass fc = new FooClass(); // or whatever, provided that fc is a FooClass instance
Object foo = cl.get(fc);
I'm assuming cl is a java.lang.reflect.Field. The documentation states that Fields' get-method will throw:
IllegalArgumentException - if the specified object is not an instance
of the class or interface declaring the underlying field (or a
subclass or implementor thereof).
You should be passing the RenderManager-object to the get-method instead of the field (unless it's static, which it is not according to your example).
vim Test.java
import java.util.*;
import com.dp4j.*;
class FooClass{
private static Map entityRenderMap;
FooClass(){
entityRenderMap = new HashMap();
}
}
public class Test{
#Reflect
public static void main(String... args){
Map reflectEntityMap = FooClass.entityRenderMap;
}
}
javac -cp ~/ws/dp4j/dp4j.jar -Averbose=true Test.java
Test.java:16: Note:
import java.util.*;
import com.dp4j.*;
class FooClass {
private static Map entityRenderMap;
FooClass() {
entityRenderMap = new HashMap();
}
}
public class Test {
public Test() {
super();
}
#Reflect()
public static void main(String... args) throws java.lang.ClassNotFoundException, java.lang.NoSuchFieldException, java.lang.IllegalArgumentException, java.lang.IllegalAccessException {
java.lang.reflect.Field entityRenderMapField = null;
entityRenderMapField = Class.forName("FooClass").getDeclaredField("entityRenderMap");
entityRenderMapField.setAccessible(true);
Map reflectEntityMap;
reflectEntityMap = (.java.util.Map)entityRenderMapField.get("");
}
}

Getting value of public static final field/property of a class in Java via reflection

Say I have a class:
public class R {
public static final int _1st = 0x334455;
}
How can I get the value of the "_1st" via reflection?
First retrieve the field property of the class, then you can retrieve the value. If you know the type you can use one of the get methods with null (for static fields only, in fact with a static field the argument passed to the get method is ignored entirely). Otherwise you can use getType and write an appropriate switch as below:
Field f = R.class.getField("_1st");
Class<?> t = f.getType();
if(t == int.class){
System.out.println(f.getInt(null));
}else if(t == double.class){
System.out.println(f.getDouble(null));
}...
R.class.getField("_1st").get(null);
Exception handling is left as an exercise for the reader.
Basically you get the field like any other via reflection, but when you call the get method you pass in a null since there is no instance to act on.
This works for all static fields, regardless of their being final. If the field is not public, you need to call setAccessible(true) on it first, and of course the SecurityManager has to allow all of this.
I was following the same route (looking through the generated R class) and then I had this awful feeling it was probably a function in the Resources class. I was right.
Found this:
Resources::getIdentifier
Thought it might save people some time. Although they say its discouraged in the docs, which is not too surprising.
I was looking for how to get a private static field and landed here.
For fellow searchers, here is how:
public class R {
private static final int _1st = 0x334455;
}
class ReflectionHacking {
public static main(String[] args) {
Field field = R.class.getFieldDeclaration("_1st");
field.setAccessible(true);
int privateHidenInt = (Integer)field.get(null);
}
}

Categories

Resources