I was trying to fetch the value of an static private attribute via reflection, but it fails with an error.
Class class = home.Student.class;
Field field = studentClass.getDeclaredField("nstance");
Object obj = field.get(null);
The exception I get is:
java.lang.IllegalAccessException: Class com.test.ReflectionTest can not access a member of class home.Student with modifiers "private static".
Moreover, there is a private I need to invoke, with the following code.
Method method = studentClass.getMethod("addMarks");
method.invoke(studentClass.newInstance(), 1);
but the problem is the Student class is a singleton class, and constructor in private, and cannot be accessed.
You can set the field accessible:
field.setAccessible(true);
Yes it is. You have to set them accessible using setAccessible(true) defined in AccesibleObject that is a super class of both Field and Method
With the static field you should be able to do:
Class class = home.Student.class;
Field field = studentClass.getDeclaredField("nstance");
field.setAccessible(true); // suppress Java access checking
Object obj = field.get(null); // as the field is a static field
// the instance parameter is ignored
// and may be null.
field.setAccesible(false); // continue to use Java access checking
And with the private method
Method method = studentClass.getMethod("addMarks");
method.setAccessible(true); // exactly the same as with the field
method.invoke(studentClass.newInstance(), 1);
And with a private constructor:
Constructor constructor = studentClass.getDeclaredConstructor(param, types);
constructor.setAccessible(true);
constructor.newInstance(param, values);
Yes, you can "cheat" like this:
Field somePrivateField = SomeClass.class.getDeclaredField("somePrivateFieldName");
somePrivateField.setAccessible(true); // Subvert the declared "private" visibility
Object fieldValue = somePrivateField.get(someInstance);
Related
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.
I have the following class:
public final class ClassMap {
public static final Class HELLO = HelloActivity.class;
}
I want to be able to access HelloActivity.class knowing the string "HELLO". I've tried the following:
Field classField = ClassMap.class.getField("HELLO");
But that returns a Field object. How can I get a Class object back?
Thanks!
Now that you have the Field object representing the field, ask for the value, i.e. call classField.get(Object obj).
Since your field is static, the obj parameter will be ignored, and you should just give a null value. Javadoc says so:
If the underlying field is a static field, the obj argument is ignored; it may be null.
So, do this:
Field classField = ClassMap.class.getField("HELLO");
Object value = classField.get(null);
I have a class that is going to be passed into a function and it will be defined as follows:
class ayy{
String blah;
Class a;
Class b;
}
I want to be able to invoke the getSimpleName() method on the classes a and b. Currently I am doing it as follows:
Class c = (Class)argument; // Where argument is the "ayy" class
c.getField("a").getSimpleName();
But this gives me an error saying "getSimpleName()" is not defined for type field.
You cannot call a method directly on an object that results from reflection, such as you're doing with Field, as if it were a reference variable of the desired type.
Instead, you'll need to call getDeclaredField, because getField only gets public fields. Also, you'll need to get() the value of the Field, passing in an instance of the ayy class, which will return the value of the Field. Then you'll need to cast it to a Class, because get() returns an Object. Then you can call getSimpleName().
Class<?> classOfA = (Class<?>) c.getDeclaredField("a").get(anAyy);
String simpleName = classOfA.getSimpleName();
You'll also need to catch the various reflection-related exceptions that may be thrown.
My code looks like the following:
class MyObject {
MyField f = new MyField();
}
class MyField {
public void greatMethod();
}
Is there a way to invoke the greatMethod() using reflection on a object of the class MyObject?
I tried the following:
Field f = myObject.getClass().getDeclaredField("f");
Method myMethod = f.getDeclaringClass().getDeclaredMethod("greatMethod", new Class[]{});
myMethod.invoke(f);
But instead it is trying to call greatMethod() on my myObject directly and not on the field f in it. Is there a way to achieve this without need to modify the MyObject class (so that it would implement a method which calls the appropriate method on f).
You were close yourself, you just need to get the declared method and invoke it on the instance of the field that is containted within your object instance, instead of the field, like below
// obtain an object instance
MyObject myObjectInstance = new MyObject();
// get the field definition
Field fieldDefinition = myObjectInstance.getClass().getDeclaredField("f");
// make it accessible
fieldDefinition.setAccessible(true);
// obtain the field value from the object instance
Object fieldValue = fieldDefinition.get(myObjectInstance);
// get declared method
Method myMethod =fieldValue.getClass().getDeclaredMethod("greatMethod", new Class[]{});
// invoke method on the instance of the field from yor object instance
myMethod.invoke(fieldValue);
Why when i try to invoke the method i get:
java.lang.IllegalArgumentException: object is not an instance of declaring class
My code:
Class<?> tWCCamRes = tCLSLoader.loadClass("com.github.sarxos.webcam.WebcamResolution");
Field tVGA = tWCCamRes.getDeclaredField("VGA");
Method tMeth = tVGA.getDeclaringClass().getDeclaredMethod("getSize");
tMeth.invoke(tVGA, (Object[]) null); // Error
In theory I pass the object instance but it failed.
Thanks in advance :)
You're calling the method getSize(), using reflection, on an object of type Field (tVGA), instead of calling it on the value of this field, which is of type WebcamResolution.
Assuming that you really need to do this via reflection, the code should be:
Class<?> tWCCamRes = tCLSLoader.loadClass("com.github.sarxos.webcam.WebcamResolution");
Field tVGA = tWCCamRes.getDeclaredField("VGA");
Object vgaFieldValue = tVGA.get(null); // it's a static field, so the argument of get() can be null.
Method tMeth = tVGA.getDeclaringClass().getDeclaredMethod("getSize");
tMeth.invoke(vgaFieldValue);
You invoke the getSize method on the field tVGA, but the method is declared on com.github.sarxos.webcam.WebcamResolution.
If you want to invoke an instance method you have to pass the instance as the inovke method's first argument.
If the method doesn't take an argument like com.github.sarxos.webcam.WebcamResolution.getSize()
Just invoke it this way:
tMeth.invoke(webcamResolutionObj);
But why don't you just use the WebcamResolution enum.
String enumName = "VGA";
WebcamResolution wcResolution = WebcamResolution.valueOf(enumName);
Dimension size = wcResolution.getSize();