0

I tried to write the following method:

public static long[] deepDoubleToLong(double... original)
{
    long[] ret = new long[original.length];
    for(int i = 0; i < ret.length; i++)
        if (original[i] instanceof double[])
            ret[i] = deepDoubleToLong((double[])original[i]);
        else
            ret[i] = (long)original[i];
    return ret;
}

bit I get this compile error:

Uncompilable source code - unexpected type
  required: reference
  found:    double
    at ArrayConversion.deepDoubleToLong(ArrayConversion.java:5)

How else, if not this way, can I tell if an item is an array?

4
  • 3
    How would it be an array? original is a double[]. Commented Feb 13, 2014 at 23:39
  • @SotiriosDelimanolis That's another part of the problem... :/ Commented Feb 13, 2014 at 23:39
  • @Supuhstar: The way it's written, the elements can't possibly be an array. Commented Feb 13, 2014 at 23:40
  • 2
    Your question is not clear to me. You're asking "How can you check if an element of a double[] is an array?". It can't, so there's no point to check. Commented Feb 13, 2014 at 23:40

4 Answers 4

1

If you change the parameter type to Object... original, use Class#isArray(), like this:

if (original[i].getClass().isArray())
Sign up to request clarification or add additional context in comments.

1 Comment

original[i] is of type double.
0

I suspect you are looking for my Rebox class.

The problem (as the comment at the start describes) comes when you call a varargs method with an array as a parameter. This causes the array to be wrapped up and appears as an array of primitives in the first parameter - or something like that.

Anyway - use this - it does what you need.

/**
 * Can rebox a boxed primitive array into its Object form.
 * 
 * Generally I HATE using instanceof because using it is usually 
 * an indication that your hierarchy is completely wrong.
 * 
 * Reboxing - however - is an area I am ok using it.
 *
 * Generally, if a primitive array is passed to a varargs it
 * is wrapped up as the first and only component of an Object[].
 *
 * E.g.
 *
 * public void f(T... t) {};
 * f(new int[]{1,2});
 *
 * actually ends up calling f with t an Object[1] and t[0] the int[].
 *
 * This unwraps it and returns the correct reboxed version.
 *
 * In the above example it will return an Integer[].
 *
 * Any other array types will be returned unchanged.
 *
 * @author OldCurmudgeon
 */
public class Rebox {
  public static <T> T[] rebox(T[] it) {
    // Default to return it unchanged.
    T[] result = it;
    // Special case length 1 and it[0] is primitive array.
    if (it.length == 1 && it[0].getClass().isArray()) {
      // Which primitive array is it?
      if (it[0] instanceof int[]) {
        result = rebox((int[]) it[0]);
      } else if (it[0] instanceof long[]) {
        result = rebox((long[]) it[0]);
      } else if (it[0] instanceof float[]) {
        result = rebox((float[]) it[0]);
      } else if (it[0] instanceof double[]) {
        result = rebox((double[]) it[0]);
      } else if (it[0] instanceof char[]) {
        result = rebox((char[]) it[0]);
      } else if (it[0] instanceof byte[]) {
        result = rebox((byte[]) it[0]);
      } else if (it[0] instanceof short[]) {
        result = rebox((short[]) it[0]);
      } else if (it[0] instanceof boolean[]) {
        result = rebox((boolean[]) it[0]);
      }
    }
    return result;
  }

  // Rebox each one separately.
  private static <T> T[] rebox(int[] it) {
    T[] boxed = makeTArray(it.length);
    for (int i = 0; i < it.length; i++) {
      boxed[i] = (T) Integer.valueOf(it[i]);
    }
    return boxed;
  }

  private static <T> T[] rebox(long[] it) {
    T[] boxed = makeTArray(it.length);
    for (int i = 0; i < it.length; i++) {
      boxed[i] = (T) Long.valueOf(it[i]);
    }
    return boxed;
  }

  private static <T> T[] rebox(float[] it) {
    T[] boxed = makeTArray(it.length);
    for (int i = 0; i < it.length; i++) {
      boxed[i] = (T) Float.valueOf(it[i]);
    }
    return boxed;
  }

  private static <T> T[] rebox(double[] it) {
    T[] boxed = makeTArray(it.length);
    for (int i = 0; i < it.length; i++) {
      boxed[i] = (T) Double.valueOf(it[i]);
    }
    return boxed;
  }

  private static <T> T[] rebox(char[] it) {
    T[] boxed = makeTArray(it.length);
    for (int i = 0; i < it.length; i++) {
      boxed[i] = (T) Character.valueOf(it[i]);
    }
    return boxed;
  }

  private static <T> T[] rebox(byte[] it) {
    T[] boxed = makeTArray(it.length);
    for (int i = 0; i < it.length; i++) {
      boxed[i] = (T) Byte.valueOf(it[i]);
    }
    return boxed;
  }

  private static <T> T[] rebox(short[] it) {
    T[] boxed = makeTArray(it.length);
    for (int i = 0; i < it.length; i++) {
      boxed[i] = (T) Short.valueOf(it[i]);
    }
    return boxed;
  }

  private static <T> T[] rebox(boolean[] it) {
    T[] boxed = makeTArray(it.length);
    for (int i = 0; i < it.length; i++) {
      boxed[i] = (T) Boolean.valueOf(it[i]);
    }
    return boxed;
  }

  // Trick to make a T[] of any length.
  // Do not pass any parameter for `dummy`.
  // public because this is potentially re-useable.
  public static <T> T[] makeTArray(int length, T... dummy) {
    return Arrays.copyOf(dummy, length);
  }
}

I may be wrong though.

Use it like this:

public StringBuilder add(StringBuilder s, T... values) {
  // Remember to rebox it in case it's a primitive array.
  for (T v : Rebox.rebox(values)) {
    add(s, v);
  }
  return s.append(fin());
}

In answer to your question title How can I tell if an item in an array is also an array? - use it[i].getClass().isArray()

Comments

0

The use of the variable argument operator (...) itself is creating an array local to your method (in this case dubbed "original"), so anything you pass to it will become an array. So are you planning on passing both multi and single dimensional arrays to this method, and then have the method distinguish between the types? If you are not declaring any multi dimensional arrays in your class, then checking for them would be entirely unnecessary. If you do have singles and multis that you want to type cast I might suggest overloading methods, and have the method arguments themselves do the separating. So something like:

public static long[] doubleToLong(double[][] original, int index){
//your conversion logic here that will type cast your second dimension array
long[] ret = new long[original.length];    
for(int i = 0; i < ret.length; i++)
     ret[i] = (long)original[index][i];
return ret;
}

public static long[] doubleToLong(double[] original){
//your conversion logic here that type casts a single dimension array
long[] ret = new long[original.length];    
for(int i = 0; i < ret.length; i++)
     ret[i] = (long)original[i];
return ret;
}

That compiled for me, see if it does for you, and also test it to make sure it does what you want. But the method arguments will sort through which arrays are single, and which are multidimensional.

Hope it helps! Happy coding!

1 Comment

> "are you planning on passing both multi and single dimensional arrays to this method, and then have the method distinguish between the types?" Yes, I am, but I'd hoped this might be more generic: allowing whomever calls the method to pass an n dimensional array and get it back as a different type
0

Here's a solution that worked for me:

import java.util.Arrays;

public class ArrayConversion
{
    public static Object[] deepToDouble(Object[] original)
    {
        Object[] ret = new Object[original.length];
        for(int i = 0; i < ret.length; i++)
            if (original[i] instanceof Object[])
                ret[i] = deepToDouble((Object[])original[i]);
            else
                ret[i] =
                (
                    original[i] instanceof Number
                        ? ((Number)original[i]).doubleValue()
                        : Double.NaN
                );
        return ret;
    }

    public static void main(String... args)
    {
        Object[] test = new Object[]{1, new Object[]{1, 2, 3}, 3};
        System.out.println(Arrays.deepToString(test));
        System.out.println(Arrays.deepToString(deepToDouble(new Object[]{1, new Object[]{1, 2, 3}, 3})));
    }
}

And the output is:

[1, [1, 2, 3], 3]
[1.0, [1.0, 2.0, 3.0], 3.0]

I know it's still loosely typed as Object, but it is now an array of doubles, which is my end goal

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.