2

How can I tell what type of class is inside a Collection? I need to handle simple data types differently than complex types and therefore I must know the contained class. At the moment, I have to iterate through the collection to find out the class which doesn't sound right. This link was quite helpful but didn't fully address my issue. Basically, here are the questions: 1. How to determine the class inside the collection? 2. how can I tell if the object is a java wrapper class (Integer, String, Date, etc..) or a proprietary class (Student, Vehicle, etc...).

Thank you Jabawaba

entity = new SomeObject();
Class entityClass = entity.getClass();
for (Method method : entityClass.getDeclaredMethods()) {
  Class<?> returnType = method.getReturnType();
  if (returnType != null) {
    if (returnType.isPrimitive() || (returnType.getName().startsWith("java.lang.")) || (returnType == java.util.Date.class)) {
      // handling primitive and wrapper classes
      handleScalar(method);
    } else if (Collection.class.isAssignableFrom(returnType)) {
      Collection collection = (Collection) method.invoke(entity);
      if (collection == null || collection.isEmpty()) {
        continue;
      }
      for (Object value : collection) {
        if (value.getClass().getName().startsWith("java.lang.") || (value.getClass() == java.util.Date.class)) {
          handleSimpleVector(method);
          // no need to go through all the simple values
          continue;
        } else {
          // Each 'value' is itself a complex object.
          handleComplexObject(method);
        }
      }
    } else if (<return-type-is-an-Array>){
      // do something similar as the above.
    }
  }
}
Community
  • 1
  • 1
jabawaba
  • 279
  • 1
  • 6
  • 16
  • You've come along way according to the code you posted. So what do you try to accomplish and at what point are you stuck? – M Platvoet Aug 11 '11 at 19:08
  • @Platvoet. I'm trying to differentiate the *return* types between: (a) public long getDistance(); (b) public List getCounts(); (c) public List getCars(); (d) public Long[] getSizes(); Because I am writing a wrapper for Lucene/Solr and I need to know the accessor's return type to decide what kind of Solr Field I should use. – jabawaba Aug 11 '11 at 19:12
  • What are you trying to accomplish? I feel there is a better way and you're just using the wrong tools. – Amir Raminfar Aug 11 '11 at 19:12
  • Let me rephrase that, just like Amir I'm wondering what the purpose of this piece of code is. Why do you need to differentiate between these methods? There might be a different approach which better suits your needs. – M Platvoet Aug 11 '11 at 19:18
  • So you basically want to store just any class in Lucene? In that case you might consider using java's serializable system. Provide your own ObjectInputStream and ObjectOutputStream. – M Platvoet Aug 11 '11 at 19:30

5 Answers5

4

1) You simply can't if it's not a generically typed Collection. Non-typed Collections can contain any mixture of object types.

If you're dealing with a (non-empty) typed Collection, then you could determine the class of its contents at runtime e.g. by

Collection<?> coll = ...
if (coll.isEmpty())
    throw new BadLuckException();
Object representative = coll.iterator().next();
Class<?> typeOfContent = representative.getClass();
//apply your cases on this Class object

There's no other way to determine the generic type information at runtime since the generic type is purely compile-time information.

2) Date is not a wrapper class - the primitive classes and their wrappers are:

  • short / Short
  • int / Integer
  • long / Long
  • byte / Byte
  • char / Char
  • double / Double
  • float / Float
  • boolean / Boolean

You can determine whether your class is a primitive one using Class#isPrimitive. Note, however, that this will only determine whether an object is really primitive, it will not determine whether you are dealing with an autoboxed value:

System.out.println(Integer.class.isPrimitive()); // -> false

But, every wrapper class declares a field named "TYPE" that represents the primitive class it is wrapping. So you can check whether a class is a wrapper class like this:

public static boolean isWrapperClass(Class<?> clazz) {
    try {
        clazz.getDeclaredField("TYPE");
        return true;
    catch (NoSuchFieldException ex) {
        return false;
    }
}
emboss
  • 38,880
  • 7
  • 101
  • 108
  • Thanks for confirming my suspicion. How about a more elegant way than shown above for determining wrapper/primitive vs non-standard class? – jabawaba Aug 11 '11 at 19:09
  • See my edit - I'm afraid there's no other way than the ugly one of comparing the classes explicitly. – emboss Aug 11 '11 at 19:35
0

Why can't you just do?

Collection c = new ArrayList();
c.add("Hi");
Iterator i = c.iterator();
Object v = i.hasNext()? i.next() : null;
if(v != null) {
    System.out.println(v.getClass().getName());
}

Update:

Assuming it is a homogeneous collection. Hopefully I correctly understood your problem.

AppleGrew
  • 9,302
  • 24
  • 80
  • 124
  • I am already doing that in the sample code. I do *not* want to iterate thru the generic collection to figure out the contained class type. – jabawaba Aug 11 '11 at 19:06
0

Looking at your example (Integer, String, Date, etc..), I'd simply create a Set containing all the types you want to handle differently and then just check if value type is in this set. You still have to iterate trough collection elements or assume that all elements of collection are of the same type.

Eugene Kuleshov
  • 31,461
  • 5
  • 66
  • 67
-1

You can't determine the type arguments for an unknown collection at run time. That information simply is not kept by the JVM at run time.

hmakholm left over Monica
  • 23,074
  • 3
  • 51
  • 73
  • Of course you can. You can do getClass on any object. I think what you mean is the generic type. Which is partially true. – Amir Raminfar Aug 11 '11 at 19:07
  • You can detect the _erased_ type of the collection itself, but there is no way to get at its generic type **arguments** (notice that word in the answer?). You can try to look at the elements themselves, but if there are none or they are all nulls, that will leave you none the wiser. – hmakholm left over Monica Aug 11 '11 at 19:07
-1

I think you can use the instanceof keyword like this:

if(s instanceof java.lang.String)
{

}

Link to examples

love_me_some_linux
  • 2,661
  • 1
  • 15
  • 7