-1

I have done my research but I still can't call it if it is possible or not. This question will sound as a special case. However, I tried to generalize it as much as I could.

In Java, I know that it is possible to use reflection to expose object's fields (say x). And I know that it is possible to go deeper and expose the fields of a the sub objects e.g. x's fields. However, when it comes to generic objects this becomes tricky.

To better explain this, assume we have the following two simple classes:

package reflection;

import java.util.*;

public class Subject {

    public List<SomeUserDefinedObj> myListOfObj =
            new ArrayList<SomeUserDefinedObj>();

    public SomeUserDefinedObj singleObj = new SomeUserDefinedObj();

    public Subject(){
        myListOfObj.add(new SomeUserDefinedObj());
    }

}

and

package reflection;

public class SomeUserDefinedObj {

    public int x;

}

And we have the following test class that will examine the Subject through reflection

package reflection;

import java.lang.reflect.*;

public class Test {

    public static void main(String[] args) {
        Subject subject = new Subject();

        Class<?> c = subject.getClass();   
        for (Field field:c.getDeclaredFields()){
            System.out.println("Field in " + c.getName() + ": " + field.getName());

            Class<?> nestedClass = field.getType();
            for (Field nestedField:nestedClass.getDeclaredFields()){
                System.out.println("\tField in " + nestedClass.getName() + ": " + nestedField.getName());
            }
        }        
    }
}

The output of this test would be:

Field in reflection.Subject: myListOfObj
Field in reflection.Subject: singleObj
    Field in reflection.SomeUserDefinedObj: x

Now, as we can see the content of the single object is retrieved, but the list is as if it is empty. I'm aware that there are ways to get the type of the list (from which you can iterate over the objects within the list) using the instance of the object itself e.g. subject from Test like here. For example, I can do Object myInstance = field.get(subject); and from their I will able to determine the type of the elements in the list and iterate over them (tested and works).

However, (and here where my question might be specific) I don't have access to the instance (due to working with legacy code which design is preventing such luxury). So, I'm trying to reach this goal with only using the reflected class object e.g. c from Test. I have found some resources that will help me determine the type of the elements in the list like in here and here (I tested them and they work). However, this (first) doesn't grantee the actual type since the type could be an abstract class, (second) I can't see any way of getting the list's elements information from there regardless of the type being abstract or not. As far as I understand, retrieving the type given this method only guarantee that it will return to you the type that initialized with the list but not the elements (and even the type could be inaccurate as explained).

Finally, the resources that I have read don't state firmly if it is possible or not to achieve such goal given all the circumstances I stated (working only with the reflected object not the actual instance of the object). So, the question become, is it possible to retrieve a Collection elements without having access to the actual instance using reflection?

Community
  • 1
  • 1
ziyadoof
  • 21
  • 1
  • 3
  • Not in the general case. Compile time generics are stored in the source code, and [accessible through reflection](http://stackoverflow.com/a/3942033/2071828), but the generics themselves are [_erased_ at compile time](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) so you cannot access runtime generics types. This means that you can access the type of your `Collection` in your example as it is "hardcoded" - if the `class Subject` was generic in the type of the `Collection` this would not be possible. – Boris the Spider Jan 14 '17 at 20:46
  • What it is the difference between a generic class that extends the Collection, and a user defined generic type class. I'm asking this because, in one of my tests I tried to create my own generic type class (nothing fancy it holds and returns a type). And using reflection as in the example above I was able to retrieve its elements! – ziyadoof Jan 14 '17 at 21:05
  • The point is that if you have _somewhere_ written the actual generic type you can then trace it though type parameters to work out the runtime generic type. This can be _extremely complicated_ in reality, and is not generally possible as some generic types are determined at runtime - for example with deserializing stuff. For an excellent example see Spring's [`GenericTypeResolver`](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/GenericTypeResolver.html) - open source and tested code is an excellent source of information. – Boris the Spider Jan 14 '17 at 21:09

1 Answers1

0

Fields only have values for a specific instance of the corresponding class.

So the simple answer is: without an instance, you can not access values of fields (unless the field is state).

Imagine that a class represents the blue print of a box. When you are now interested in the content of such a box... You still need one real box to look into.

But: when you are able to execute code within the same JVM where your application runs... Then it might somehow be possible to access them. You need to find out if other objects known to you could contain those boxes you would like to look into.

GhostCat
  • 127,190
  • 21
  • 146
  • 218
  • That's true, but in the example `List` is a property of the `class` so you can get its generic type via reflection. This is not true in the general case. – Boris the Spider Jan 14 '17 at 20:47
  • The thing that I don't understand is that Fields are created based on "real" instances, thus I was trying hardly to get all the information from them without going back to the actually instance. In regard of your second point, I thought of that, but the issue is that I don't have much information about the elements from the list field (e.g. name, or byte code) – ziyadoof Jan 14 '17 at 21:12