Nir
Nir

Reputation: 2657

Array parameter behavior on java

I just notice a weird behavior, look at the example:

  public static void main(String[] args) {  
    aaa(1,2);
  }

  public static void aaa(int... a){
    bbb(a);
    ccc(a);
  }

  public static void bbb(int... a){

  }

  public static void ccc(Object... a){

  }

On bbb a is an array {1,2} (a = {1,2})

On ccc a is an array of array's which the first array value is {1,2} (a = { {1,2} })

There are places on my code that I must define it as Object. But of course the second behavior is not desired.. I want the same behavior for both definitions (both Object... and int... will contain {1,2}). How do I do it?

The preferred value is an array of values and not and array of arrays. For example bbb parameter is ok, and the desired parameter in ccc is {1,2} from type Object.

If will try to do something like this is order to get the inner array I will fail:

  public static void ccc(Object... a){
    ArrayList<Object> list = new ArrayList<>();
    if(a.getClass().isArray()){
      for(Object in_obj: (Object[])obj){
        list.add(in_obj);
      }
    }

    // rest of the code..
  }

Error: java.lang.ClassCastException: I cannot be cast to java.lang.Object[] because the array is primitive.. Is there a solution for that? I dont use only with int, but with a lot of primitive(and not primitive)..

Upvotes: 3

Views: 105

Answers (3)

Nir
Nir

Reputation: 2657

Thank you for your input, I want also credit this thread. What I've build is this:

  private Object[] toArrayObject(Object[] array){   
    ArrayList<Object> list = new ArrayList<>();
    for(Object obj: array){
      if(obj.getClass().isArray()){
        list.addAll(Arrays.asList(getArray(obj)));
      } else{
        list.add(obj);
      }
    }

    return list.toArray();
  }

  private Object[] getArray(Object val){
    Class<?>[] ARRAY_PRIMITIVE_TYPES = { 
        int[].class, float[].class, double[].class, boolean[].class, 
        byte[].class, short[].class, long[].class, char[].class 
    };

    Class<?> valKlass = val.getClass();
    Object[] outputArray = null;

    for(Class<?> arrKlass : ARRAY_PRIMITIVE_TYPES){
      if(valKlass.isAssignableFrom(arrKlass)){
        int arrlength = Array.getLength(val);
        outputArray = new Object[arrlength];
        for(int i = 0; i < arrlength; ++i){
          outputArray[i] = Array.get(val, i);
        }
        break;
      }
    }
    if(outputArray == null) // not primitive type array
        outputArray = (Object[])val;

    return outputArray;
  }

Upvotes: 1

Jason C
Jason C

Reputation: 40406

Java will not autobox an int array into an Integer array. One thing you could do is, in ccc, go through each Object in a and check if it is an int[], and if so, process those ints separately.

Another thing you could do is box the int array first; either write your own method to do it, or e.g. Apache Commons Lang provides ArrayUtils.toObject().

You could also just use Integer all around to begin with.

Still, if you find yourself in this situation, you should take a step back and think about whether or not what you're doing makes the most sense.

Upvotes: 0

Dev Blanked
Dev Blanked

Reputation: 8885

Use Integer instead of int.

public static void main(String[] args) {  
    aaa(1,2);
  }

  public static void aaa(Integer... a){
    bbb(a);
    ccc(a);
  }

  public static void bbb(Integer... a){

  }

  public static void ccc(Object... a){

  }

Upvotes: 0

Related Questions