How to get the values of generic array in Java?

3.5k Views Asked by At

I want to get the real value of a generic class member (an array) in Java. I have googled it for several hours but have not found a clear answer. Honestly, I'm new to Java and this generic stuff.

public class Box<T> {
    private T t;

    public Box(T t) { this.t = t; }

    public void getTheT() {
        // get the value of t at index 0
        System.out.println(this.t[0]); // this doesn't work
    }
}

public class App {
    public static void main(String[] args) {
        Integer[] Arr = {2,3,4};
        Box<Integer[]> i = new Box<Integer[]>(Arr);
        i.getTheT();

    }
}

I've updated my question. Maybe this time it's clearer. How can I get the original value of t?

4

There are 4 best solutions below

1
On BEST ANSWER

You should simply cast t to its original type Integer[], like this :

public class Box<T>{
    private T t;

    public Box(T arr){this.t = arr; } // you forget this semi-colon

    public void getTheT(){
        // get the value of t at index 0
        if(t.getClass() == Integer[].class){
            System.out.println("t[0]:"+((Integer[])t)[0]); // prints 2
        }
        else
            System.out.println(t);
    }

}


public class App{
    public static void main(String[] args){
        Integer[] Arr = {2,3,4};
        Integer i1 = 3;        
        Box<Integer> i = new Box<Integer>(i1);
        i.getTheT();
        Box<Integer[]> ia = new Box<Integer[]>(Arr);
        ia.getTheT();

    }
}
0
On

Assuming your Box will always hold arrays then the simplest solution is to make your type parameter T be the element type instead of the array type (e.g., Integer instead of Integer[]) then make the private variable be of type T[] rather than T. Then Box will always have easy access to the array elements, and can also conveniently use any java.util.Arrays methods such as toString on it:

public class Box<T> {
    private T[] t;

    public Box(T[] t) { this.t = t; }

    public void getTheT() {
        System.out.println(t[0]); // access individual elements
        System.out.println(java.util.Arrays.toString(t)); // print the lot
    }
}

public class App {
    public static void main(String[] args) {
        Integer[] Arr = { 2, 3, 4 };
        Box<Integer> i = new Box<>(Arr); // not Box<Integer[]> any more
        i.getTheT();
    }
}

The catch is that since Java generics do not currently work with primitive types, you will have to put up with the overhead of object/boxed types (e.g., Integer instead of int).


If you want to keep T as the array type itself (perhaps because you want to allow Box<int[]>, since Box<int> is not possible) then it gets more tricky. In that case you can't simply use [...].

You can use the methods of java.util.reflect.Array to get access to arbitrary arrays' elements no matter what variable type they are stored in. This gives basic get and set access, but the methods are somewhat slow (fine for debugging but not for much else):

public class Box<T> {
    private T t;

    public Box(T t) { this.t = t; }

    public void getTheT() {
        // print all array elements
        for (int i = 0, len = java.lang.reflect.Array.getLength(t); i < len; i++) {
            System.out.println(java.lang.reflect.Array.get(t, i));
        }
    }
}

public class App {
    public static void main(String[] args) {
        int[] Arr = { 2, 3, 4 };
        Box<int[]> i = new Box<>(Arr); // primitive array element type!
        i.getTheT();
    }
}

Unfortunately there is currently no nice, performant way in Java to write code that can work with elements of all arrays, regardless of their types. Instead, such code has to be written nine times as you see the methods of java.util.Arrays are. That's once for element type Object (and everything that extends Object), and then once each for the primitive element types (boolean, byte, short, char, int, long, float, double).

0
On

It clearly depends on the object type. The default implementation of toString which is called by System.out.println wil return this kind of information. It is the really value. If you want another formatting you'll have to do it by hand maybe by enclosing your array in an object.

class Custom {

    private Integer[] arr;
    //Constructor

    @Override
    public String toString(){
        String line = "";
        for (int i : arr) {
            line += i + ",";
        }
        //take off last ","
        return line;
    }
}
3
On

"Value" here depends on how you define it. If you want to print the "value" of an Object in your case you may want to override the toString method. Since you can't override the implementation of an array you have to check for it. There are a lot of libraries around which can do this for you (in Apache Commons for example). In your case you can use the Arrays.deepToString() method.