1

I get the class type of the nested classes in debug mode, but I can' t create an instance to initialize in the next step the Fields of the nested instance. (See my comented lines). So my Unit test fails with Error.

public class Reflector {
public static <T> T initialize(Class<? extends T> clazz) {

    try {
        Object classInstance = clazz.newInstance();
        System.out.println("MainclassInstance: "+ classInstance.toString());

        for (Field field : clazz.getDeclaredFields()) {

            System.out.println(
             "\n### 1. For-Schleife\nclazz.getDeclaredFields().size(): " + clazz.getDeclaredFields().length);

            System.out.println("clazz.field: " + field.getName());

            //Class Object
            if (field.getType().isMemberClass()) {

                Object memberClassInstance = field.getType();      //Nested$FirstNested

                System.out.println("memberClassInstance: " + memberClassInstance.toString()); //Nested$FirstNested

                List<Field> memberClassFields = Arrays.asList(((Class<?>) memberClassInstance).getDeclaredFields());

                for (int memberFieldIndex = 0; memberFieldIndex < memberClassFields.size() - 1; memberFieldIndex++) {
                    System.out.println("meberClassField: " + memberClassFields.get(memberFieldIndex).getName());


                    //memberClassFields.get(memberFieldIndex).set(memberClassInstance, "nestedField");
                }
                //field.set(memberClassInstance, "MyObject");
                //field.set(classInstance, memberClassInstance);
            }

        }

        return (T) classInstance;

    } catch (SecurityException | IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InstantiationException ex) {
        Logger.getLogger(Reflector.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        Logger.getLogger(Reflector.class.getName()).log(Level.SEVERE, null, ex);
    }

    return null;
}

This is the JUnit test class

public class ReflectorTest {

    @Test
    public void testInitializeNestedObject() {
        Nested actual = Reflector.initialize(Nested.class);

        assertNotNull(actual);
        assertNotNull(actual.nested1);
        assertTrue(actual.nested1 instanceof Nested.FirstNested);
        assertNotNull(actual.nested1.nestedField1);
        assertNotNull(actual.nested1.nestedField2);

        assertNotNull(actual.nested2);
        assertTrue(actual.nested2 instanceof Nested.SecondNested);
        assertNotNull(actual.nested2.nestedField3);
        assertNotNull(actual.nested2.nestedField4);
    }
}

This is the class for data

public class Nested {

    public class FirstNested{
        public Object nestedField1;
        public Object nestedField2;
    }

    public class SecondNested{
        public Object nestedField3;
        public Object nestedField4;
    }

    public FirstNested nested1;
    public SecondNested nested2;

}
Peter Pan
  • 11
  • 3

2 Answers2

0

The problem is that although you create instance for the container class Nested you don't create instances for the enclosed classes FirstNested and SecondNested. In order to make these kind of instances you can change your class like this

public static class Nested
{
    public static class FirstNested
    {
        public Object nestedField1;
        public Object nestedField2;
    }

    public static class SecondNested
    {
        public Object nestedField3;
        public Object nestedField4;
    }

    public FirstNested nested1;
    public SecondNested nested2;

}

You have to make the inner classes static so they can be accessed easily by reflection. Then you have to implement (maybe in a recursive way) the creation of new instances and registering those instances to your container class instance.

Something like this

Object memberClassInstance = field.getType().newInstance();
field.set(classInstance, memberClassInstance);

Or you can keep the classes as they are and use something like this

Object memberClassInstance = field.getType().getConstructor(Nested.class).newInstance()

As @CoronA mentions in the comments. More on how to instantiate inner classes can be found here How to instantiate inner class with reflection in Java?

Community
  • 1
  • 1
Alkis Kalogeris
  • 17,044
  • 15
  • 59
  • 113
  • 1
    Strictly - there is no need to change the inner classes to static ones. With non-static nested inner classes you lower statement would look like (!) `Object memberClassInstance = field.getType().getConstructor(Nested.class).newInstance()` (nested classes constructors add the outer class to their arguments). – CoronA Nov 08 '15 at 11:19
  • I deserved a down vote for that one. Thanks for giving me the chance to correct my answer. – Alkis Kalogeris Nov 08 '15 at 12:20
0

The right solution:

public class Reflector {
public static <T> T initialize(Class<? extends T> clazz) {

    try {
        Object classInstance = clazz.newInstance();
        System.out.println("MainclassInstance: " + classInstance.toString());

        for (Field field : clazz.getDeclaredFields()) {

            System.out.println(
                    "\n### 1. For-Schleife\nclazz.getDeclaredFields().size(): "
                    + clazz.getDeclaredFields().length);

            System.out.println("clazz.field: " + field.getName());


            //Class Object
            if (field.getType().isMemberClass()) {


                Object innerInstance = null;
                try {

                    Class<?> innerClass = Class.forName(field.getType().getName());
                    Constructor<?> ctor = innerClass.getDeclaredConstructor(classInstance.getClass());
                    innerInstance = ctor.newInstance(classInstance);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(Reflector.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(Reflector.class.getName()).log(Level.SEVERE, null, ex);
                } catch (NoSuchMethodException ex) {
                    Logger.getLogger(Reflector.class.getName()).log(Level.SEVERE, null, ex);
                }

                //###############
                Object memberClassInstance = field.getType();      //Nested$FirstNested

                System.out.println("memberClassInstance: " + memberClassInstance.toString()); //Nested$FirstNested

                List<Field> memberClassFields = Arrays.asList((innerInstance.getClass()).getDeclaredFields());

                for (int memberFieldIndex = 0; memberFieldIndex < memberClassFields.size() - 1; memberFieldIndex++) {
                    System.out.println("meberClassField: " + memberClassFields.get(memberFieldIndex).getName());
                    memberClassFields.get(memberFieldIndex).set(innerInstance, memberClassFields.get(memberFieldIndex).getName() + (memberFieldIndex+1));     
                }

                field.set(classInstance,innerInstance);

            }

        }

        return (T) classInstance;

    } catch (SecurityException | IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InstantiationException ex) {
        Logger.getLogger(Reflector.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        Logger.getLogger(Reflector.class.getName()).log(Level.SEVERE, null, ex);
    }

    return null;
}
Peter Pan
  • 11
  • 3