damon
damon

Reputation: 8477

converting Object returned by Field.get() to String[] in java reflection

I have a generic class which maintains an internal array(say data) and number of elements(say N) in the array (both private).I can add elements to the array ,which will update the value of N.The public API of the class doesn't have get methods for the data array or N.Still I would like to write unit tests for checking the state of array and N.

    public class InternalArray<T> {
    private T[] data;
    private int N;
    private int head;
    public InternalArray() {
        super();
        data = (T[]) new Object[10];
        N = 0;
        head = 0;
    }

    public void add(T item){
        data[head]=item;
        head++;
        N++;
    }

    public T get(){
        T item = data[--head];
        N--;
        return item;
    }
}

Here, all I can test are the public APIs .. But I need to test the internal state of the private variables . I thought I would be able to access the fields using reflection.I tried the below code, I can get the value of N. When it comes to T[] data ,I can't figure out how to convert the resulting Object to a String[] ( from call arrayf.get(inst) )

public static void demoReflect(){
        try {           
                Class t = Class.forName("InternalArray");
                System.out.println("got class="+t.getName());
                InternalArray<String> inst = (InternalArray<String>) t.newInstance();
                System.out.println("got instance="+inst.toString());

                inst.add("A");
                inst.add("B");
                Field arrayf = t.getDeclaredField("data");
                arrayf.setAccessible(true);
                Field nf = t.getDeclaredField("N");
                nf.setAccessible(true);
                System.out.println("got arrayfield="+arrayf.getName());
                System.out.println("got int field="+nf.getName());
                int nval = nf.getInt(inst);
                System.out.println("value of N="+nval);
                Object exp = arrayf.get(inst);
                //how to convert this to String[] to compare if this is {"A","B"}

        } catch (ClassNotFoundException e) {            
            e.printStackTrace();
        } catch (InstantiationException e) {            
            e.printStackTrace();
        } catch (IllegalAccessException e) {            
            e.printStackTrace();
        } catch (SecurityException e) {         
            e.printStackTrace();
        } 
        catch (IllegalArgumentException e) {            
            e.printStackTrace();
        } catch (NoSuchFieldException e) {          
            e.printStackTrace();
        }
    }

This gave the output below

got class=InternalArray
got instance=InternalArray@c2ea3f
got arrayfield=data
got int field=N
value of N=2

Upvotes: 1

Views: 4550

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726909

The Object that you get from the call of arrayf.get(inst) is of type Object[], not String[], because Java generics are implemented through type erasure. You can do this:

Object[] strings = (Object[])arrayf.get(inst);
System.out.println(strings.length);
for (int i = 0 ; i != strings.length ; i++) {
    String s = (String)strings[i];
    ...
}

P.S. I am going to stay away from the discussion on whether it's a good idea to unit test the private details of the implementation.

Upvotes: 2

Related Questions