Nathan Russell
Nathan Russell

Reputation: 3668

How to deal with a Java object that might or might not be an array, and might or might not be an array of primitives

I'm writing some code that works with the JMX api. Specifically I am making use of the getAttribute method of MBeanServerConnection

The javadocs for the getAttribute method says that it returns Object, but what I have found is that depending on the MBean, sometimes it can return an Object, and other times it can return an Object[] array.

Because I want to deal with the return from getAttribute consistently, I have written the following code:

Object attr = mBeanServer.getAttribute(objName, attributeName);
Object[] attributes = new Object[]{};

if (attr.getClass().isArray()) {
    attributes = (Object[])attr; // create my array by casting the return from getAttribute
} else {
    attributes = new Object[] {attr}; // create my array with just one element
}

for (int i=0; i < attributes.length; i++) {
    // deal with each attribute ...
}

Hopefully you can see the idea. It's probably a naive solution, but basically I want to deal with the return from getAttribute consistently, regardless of whether its a single Object or an Object[] array.

The above works ... for the most part! ... but I've now found a case where 'getAttribute' has returned an array of long (the primitive, rather than class). Because of this, my cast throws a java.lang.ClassCastException: [J cannot be cast to [Ljava.lang.Object;

I understand the exception - it cannot cast an array of long to an array of Object - but I don't know how to solve it.

Personally, I think the method signature of getAttribute sucks! Returning 'Object' to cover pretty much anything - an object, an array of objects, or an array of primitives - feels like a cop out to me. But its not my api, and I've got to work with it.

Appreciate any thoughts or ideas on how I can solve this?

Cheers

Nathan

Upvotes: 1

Views: 536

Answers (2)

splungebob
splungebob

Reputation: 5415

How about this?

import java.lang.reflect.*;
import java.util.*;

public class ArrayTest
{ 
  public static void main(String[] args)
  {
    evaluate("Hello");
    evaluate(new Boolean[]{Boolean.TRUE, Boolean.FALSE});
    evaluate(new int[]{0, 1, 2});
    evaluate(null);
  }

  public static void evaluate(Object object)
  {
    List<String> primitiveArrayTypes = Arrays.asList(new String[] {
        "boolean[]", "byte[]", "char[]", "double[]",
        "float[]", "int[]", "long[]", "short[]"
    });

    if (object == null)
    {
      System.out.println("Null object.");
      return;
    }

    Class objClass = object.getClass();

    if (objClass.isArray())
    {
      if (primitiveArrayTypes.contains(objClass.getCanonicalName()))
      {
        System.out.println("Contents of primitive array:");
        for (int i = 0; i < Array.getLength(object); i++)
        {
          System.out.println(Array.get(object, i));
        }
      }
      else
      {
        System.out.println("Contents of Object array:");
        for (Object obj : (Object[]) object)  // cast should now always work
        {
          System.out.println(obj);
        }
      }
    }
    else
    {
      System.out.println("Not an array: " + object);
    }
    System.out.println("---");
  }
}

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691765

if (o instanceof int[]) {
   ...
}
else if (o instanceof boolean[]) {
   ...
}
...

Maybe there's some more elegant solution, but you don't tell what you want to do with the attribute.

Upvotes: 1

Related Questions