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.
Related
I have a scala trait with a public UUID that has a default value:
trait pet {
var uuid_ : UUID = UUID.randomUUID
}
now I am creating multiple classes, also in scala:
class dog extends pet {
var foo = 1
}
class cat extends pet {
}
class fish extends pet {
}
After that I created a method in Java (old project with both languages mixed).
Here the snipped with my problem. In the variable somePet is an instance of dog, cat or fish. But it is not clear what of them exactly:
// printing all variables in the console for human testing
Serializer.printAllFields(somePet);
// The somePet Variable must be a pet
if(!pet.class.isAssignableFrom(somePet.getClass()))
throw new Exception("Not a pet.");
// get the UUID of the pet
UUID uuid_;
try {
Field f = pet.class.getField("uuid_");
f.setAccessible(true);
uuid_ = (UUID) f.get(somePet);
}catch(Exception e){
// no uuid found
throw e;
}
But when I run the code I get the following error:
Exception in thread "main" java.lang.NoSuchFieldException: uuid_
And the stacktrace points on the line with Field f = pet.class.getField("uuid_");.
But what is wrong with the code?
An alternative I thought was replacing this exact line with:
Field f = ntObj.getClass().getField("uuid_");
But this also fails.
So where is the variable uuid_?
Because when I print out all variables in the console of the current somePet with a Serializer, I get something like
* cat.uuid_ = 34d7a781-472d-4d98-861e-7cff08045445;
or
* dog.foo = 1
* dog.uuid_ = 34d7a781-472d-4d98-861e-7cff08045445;
in the console.
So the variable uuid_ is there with a default value.
(I am using the serializer from this post)
So how do I get the uuid_ variable in my java snippet?
First of all, there is no such Serializer under the the package java.util, so you're using something else.
An trait is translated to a Java interface, which cannot have fields per se.
However you're trying to access the field via the Pet interface
pet.class.getField(...)
That won't work. You need to look for the field inside the concrete class.
Also, the field will be private by default, since the access is granted via a getter.
The getField method is able to retrieve every public field for the entire class hierarchy (which mean even superclasses), while getDeclaredField is able to retrieve protected and private fields, but only on the exact class you're calling it from. You need also a call to setAccessible(true), because
A value of true indicates that the reflected object should suppress
Java language access checking when it is used. A value of false indicates that the reflected object should enforce Java language access checks
The correct code would be (dog is the concrete instance)
final Field uuid = dog.getClass().getDeclaredField("uuid_");
uuid.setAccessible(true);
final Object o = uuid.get(dog);
Or using the automatic getter
final Method uuid = dog.getClass().getMethod("uuid_");
final Object o = uuid_.invoke(dog);
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 basic understanding of OOP concepts, but here is a question I currently have.
Say I create this object:
Test test1 = new Test();
I then call a function within this Object
test1.toString();
And when overriding that toString() method I want to get the 'test1' object name from the main class file, so I can print it out like so...
System.out.println( "This is a test " + test1.toString() );
Prints:
This is a test test1
Thank you
The name of a local variable is only meaningful at compile time. There is no way to obtain the name of a reference.
Note: the reference and the Object are two different things.
What you can do is get the name of a field, however there is no way to find from an object where the object has been assigned.
The normal way to give an Object a name, is to give a field e.g. name
Test test1 = new Test("test1");
String str = test1.getName();
For enum there is an implicit name.
enum BuySell {
Buy, Sell;
}
BuySell bs = BuySell.Buy;
String s = bs.name(); // implicitly defined for all Enum
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.
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);