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!
Related
I have a Java class named "MyClass" with a private attribute, of type "AnotherClass". MyClass has a private constructor, and "AnotherClass" has public constructor. "AnotherClass" has also a private String field, "value", which is initialized in constructor. I want to access in "Main" class this String.
The first class:
public class MyClass {
private AnotherClass obj;
private MyClass() {
obj = new AnotherClass();
}
}
The second class:
public class AnotherClass {
private String value;
public AnotherClass() {
value = "You got the private value!";
}
}
The main class:
public class Main {
static String name;
static AnotherClass obj;
public static void main(String[] args) throws Exception {
Class myClass;
myClass = Class.forName("main.MyClass");
Constructor<MyClass>[] constructors = myClass
.getDeclaredConstructors();
for (Constructor c : constructors) {
if (c.getParameters().length == 0) {
c.setAccessible(true);
MyClass myCls= (MyClass) c.newInstance();
Field myObjField = myClass
.getDeclaredField("obj");
myObjField.setAccessible(true);
obj = (AnotherClass) myObjField.get(myCls);
// If "value" is public, the program prints "You got the private value!"
// So "obj" is returned correctly, via reflection
// name = obj.value;
// System.out.println(name);
// Now I want to get the field "value" of "obj"
Field myStringField = obj.getClass().getDeclaredField("value");
myStringField.setAccessible(true);
// This line throws an exception
name = (String) myStringField.get(obj.getClass());
System.out.println(name);
}
}
}
}
I expect to see in the console "You got the private value!", but the program throws an exception:
Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.String field main.AnotherClass.value to java.lang.Class
So, I want to retrieve the private field, "value", without modifying "MyClass" and "AnotherClass", and without calling the public constructor from AnotherClass directly in main() . I want to get the value from "obj".
Change this line
name = (String) myStringField.get(obj.getClass());
to this
name = (String) myStringField.get(obj);
The get method requires an object to access the field of (unless it's a static field)
How to read annotation which is declared over an object.
For e.g
Annotation :
AuthorInfo.java
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface AuthorInfo {
String author() default "Dushyant Kumar";
String login() default "dushyantashu";
}
What I am trying to do :
Book.java
#Data
public class Book {
private int serialNo;
private String review;
}
Main.java
public class Main {
#AuthorInfo (
author = "Barry Allen",
login = "theflash"
)
private static Book book = new Book();
public static void main(String[] args) {
showAnnotation(book);
}
private static void showAnnotation(Object object) {
// How to get values of annotation declared over this object.
}
}
My usecase is to generate this generic showAnnotation() method, that's why param is Object. How to achieve this? From what I explored, I only got ways to read annotation if it's declared over a class, or declared over a member of a class. Isn't there a way where given an object, if some annotation is present over it can be read?
Thanks
You can give a try with generics and reflection. Assume the Book class is annotated with AuthorInfo like below:
#AuthorInfo(author = "Ram", login = "ram")
public class Book {
}
Suppose if you want to know whether AuthorInfo is present in the object of Book, you can do like below. This is straight forward solution to know whether specific annotation is present in an object.
public class TestAnnotation {
public static void main(String[] args) {
Book book = new Book();
showAnnotation(book);
}
private static <T> void showAnnotation(T t) {
Class<? extends Object> aClass = t.getClass();
if (aClass.isAnnotationPresent(AuthorInfo.class)) {
System.out.println("AuthorInfo annotation present");
AuthorInfo authorInfo = aClass.getAnnotation(AuthorInfo.class);
System.out.println(authorInfo.author());
System.out.println(authorInfo.login());
}
}
}
Suppose, if you want to know all annotations on that object, something like below helps:
private static <T> void showAnnotation(T t) {
Class<? extends Object> aClass = t.getClass();
for (Annotation annotation : aClass.getAnnotations()) {
System.out.println(annotation.toString());
}
}
You can retrieve the object class and then explore it. Via Reflection you could get its fields and methods also, and check if any has annotations on it.
Annotations can be read using Reflection API. Like
Class<Main> clazz = Main.class;
Method[] methods = clazz.getDeclaredMethods();
Field[] fields = clazz.getDeclaredFields();
for (Method method : methods) {
Annotation[] annotation = method.getDeclaredAnnotations();
}
for (Field field : fields) {
//This will get #AuthorInfo annotation on book
Annotation[] annotation = field.getDeclaredAnnotations();
//This will get #Data annotation on Book class
Annotation[] annotationsOnFieldClass = field.getClass().getDeclaredAnnotations();
}
clazz.getDeclaredAnnotations();
I have a class
like below
public class SampleReflection {
public static final String TWO_name = "html";
public static final String TWO_find = "css";
public static final String ONE_KEY_java = "java";
public static final String ONE_KEY_jsp = "jsp";
public static final String ONE_KEY_oracle = "oracle";
public static final String ONE_KEY_spring = "spring";
public static final String ONE_KEY_struts = "struts";
}
I would like to get all the fields which starts with ONE_KEY and their value.
because the ONE_KEY_xxx can be of any numbers.
how to do this in java reflection or any other way in java ?
thanks
You can use SampleReflection.class.getDeclaredFields(), iterate over the result and filter by name. Then call field.get(null) to get the value of the static fields. If you want to access non-public fields as well you might have to call first.setAccessible(true) (provided the security manager allows that).
Alternatively you could have a look at Apache Common's reflection utilities, e.g. FieldUtils and the like.
Depending on what you actually want to achieve there might be better approaches though, e.g. using a map, enums etc.
In your case where you have static fields using an enum might be a better way to go.
Example:
enum SampleFields {
TWO_name("html"),
TWO_find("css"),
ONE_KEY_java("java"),
ONE_KEY_jsp("jsp");
ONE_KEY_oracle("oracle"),
...;
private String value;
private SampleFields(String v) {
value = v;
}
}
Then iterate over SampleFields.values() and filter by name.
Alternatively, if that fits your needs, you could split the names and pass a map to the enum values, e.g.
enum SampleFields {
TWO(/*build a map "name"->"html","find"->"css")*/ ),
ONE_KEY(/*build a map "java"->"java","jsp"->"jsp", ...*/);
private Map<String, String> values;
private SampleFields(Map<String, String> map) {
values = map;
}
}
Then get the enum values like this: SampleFields.valueOf("ONE_KEY").get("java")
Thanks for the answer,
this is what i was looking for,
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class SampleReflection {
public static final String TWO_name = "html";
public static final String TWO_find = "css";
public static final String ONE_KEY_java = "java";
public static final String ONE_KEY_jsp = "jsp";
public static final String ONE_KEY_oracle = "oracle";
public static final String ONE_KEY_spring = "spring";
public static final String ONE_KEY_struts = "struts";
public static void main(String[] args) {
Class<?> thisClass = null;
Map<String,String> keyValueMap = new HashMap<String,String>();
try {
thisClass = Class.forName(SampleReflection.class.getName());
Field[] aClassFields = thisClass.getDeclaredFields();
for(Field f : aClassFields){
String fName = f.getName();
if(fName.contains("ONE_KEY")){
keyValueMap.put(fName, (String)f.get(SampleReflection.class));
}
}
for (Map.Entry<String, String> entry : keyValueMap.entrySet())
{
System.out.println(entry.getKey() + "=" + entry.getValue());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
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.
I have a class as below.
public class Emp{
private String name;
private String age;
//setters and getters
}
Have one more class below.
public class Student extends Emp{
private int marks;
//setters and getters
}
is there anyway to get the fields of a subclass using super class using java Reflection?
I need to get Student fields using Emp instance.
we can get super class fields as below:
subClass.getClass().getSuperclass().getDeclaredFields();
similarly can i get sub class fields using super class?
Is it possible?
Thanks!
I may have misunderstood your question. Do you want to do something like the following?
Emp e = new Student(...);
[do something with e]
foo = e.marks;
If yes, do it like this:
foo = ((Emp)e).marks;
However, if you want to do something like the following:
Emp e = new Emp(...);
[do something with e]
e.marks = ....
Then no, it's not possible, and I'd suspect your internal model of java's object model is either incomplete or flawed.
In theory there is a very complicated and costly way by retrieving all loaded classes and checking which of them are derived from Emp and contain the field. If the desired class wasn't loaded yet this may not help either.
Not directly, you have to write a helper method to that.
You take a class and the field name (and possibly type) as parameters, then look for that field in the given class. If you cant find it, you take the class's superclass and repeat from the beginning. You do this until you either found the field, or getSuperClass() returned null (meaning you reached the root of the inheritance tree).
This example demonstrates how to call find and call a specified method on an object. You can easily extract and adapt the logic for fields.
public static Object call(final Object instance,
final String methodName,
final Class<?>[] signature,
final Object[] args) {
try {
if (instance == null)
return null;
Class<?> instanceClass = instance.getClass();
while (instanceClass != null) {
try {
final Method method = instanceClass.getDeclaredMethod(methodName, signature);
if (!method.isAccessible())
method.setAccessible(true);
return method.invoke(instance, args);
} catch (final NoSuchMethodException e) {
// ignore
}
instanceClass = instanceClass.getSuperclass();
}
} catch (final Throwable e) {
return null;
}
return null;
}
Is it what you want? But beware of using field.setAccesible.
Parent class:
public class ParentClass {
private String parentField = "parentFieldValue";
public void printFields() throws IllegalAccessException {
Field[] fields = getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Object fieldValue = field.get(this);
if (fieldValue instanceof String) {
String stringValue = (String) fieldValue;
System.out.println(stringValue);
}
}
}
}
Child class:
public class ChildClass extends ParentClass {
private String childField = "childFieldValue";
}
Usage:
public class Main {
public static void main(String[] args) throws IllegalAccessException {
ParentClass pc = new ParentClass();
ChildClass cc = new ChildClass();
pc.printFields();
cc.printFields();
}
}
This is the final solution!
#NonNull
public static List<Class<?>> getSubClasses() {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
String method = trace[3].getMethodName();
if (!"<init>".equals(method)) {
throw new IllegalStateException("You can only call this method from constructor!");
}
List<Class<?>> subClasses = new ArrayList<>();
for (int i = 4; i < trace.length; i++) {
method = trace[i].getMethodName();
if ("<init>".equals(method)) {
try {
subClasses.add(Class.forName(trace[i].getClassName()));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
} else {
break;
}
}
return subClasses;
}
this are some examples of usage:
class a {
public a(){
print(getSubClasses());
}
}
class b extends a{
}
class c extends b{
}
And the result is
new a() -> []
new b() -> [b.class]
new c() -> [b.class, c.class]