Page 1 of 2 12 LastLast
Results 1 to 20 of 31

Thread: Dynamic Casting

  1. #1
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default Dynamic Casting

    I'm working with a third party API. A function in that API returns an Object.
    This object can be anything, depending on what sort of processing went on the API.

    When the object is an array, it is always an Object array. However, the objects in the array are always homogeneous. I can get the type with reflection. I want to create an array that is typed with the homogeneous type (not Object[]) so that I can pass it to another function.

    See example below. The cast lines (Integer[]) and (Double[]) always fail at runtime with a ClassCastException. Any ideas on how to do this?

    Java Code:
    	public static void main(String[] args) {
    		Object o = getValue();
    		if (o.getClass().isArray()) {
    			Object[] oarray = (Object[])o;
    			if (oarray[0] instanceof Integer) {
    				Integer[] iarray = (Integer[])oarray;
    				print(iarray);
    			}
    			else if (oarray[0] instanceof Double) {
    				Double[] darray = (Double[])oarray;
    				print(darray);
    			}
    		}
    	}
    	
    	public static Object getValue() {
    		Object[] oarray = new Object[3];
    		
    		if (new Random().nextDouble() > 0.5) { 
    			oarray[0] = 0;
    			oarray[1] = 1;
    			oarray[2] = 2;
    		}
    		else {
    			oarray[0] = 0.0;
    			oarray[1] = 0.1;
    			oarray[2] = 0.2;
    		}
    
    		return oarray;
    	}
    	
    
    	public static void print(Double[] darray) {
    		for (double d : darray)
    			System.out.println(d);
    	}
    	
    	public static void print(Integer[] iarray) {
    		for (int i : iarray)
    			System.out.println(i);
    	}

  2. #2
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default RE: Dynamic Casting

    This wasn't a good representation of the situation.
    A solution is:

    Java Code:
    Integer[] tmparray = new Integer[oarray.length];
    for (int i = 0 ......)
      tmparray[i] = (Integer)oarray[i];
    The real problem is that the type cannot be anticipated before hand (not know if Double, or Integer, or some other thing). But other methods are expecting a typed array, not an Object array. I'd like to create a typed array based on it's contents, but there doesn't appear to be a mechanism for creating run time typed arrays.

  3. #3
    r035198x is offline Senior Member
    Join Date
    Aug 2009
    Posts
    2,388
    Rep Power
    8

    Default

    Generics don't work well with arrays.
    Why not use a List<T> instead of an array?

  4. #4
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,538
    Blog Entries
    7
    Rep Power
    20

    Default

    Downcasting the type of an array the way you wanted/suggested would be very expensive, i.e. every single element of the array needs to be tested and if the test fails an exception needs to be thrown. You have to cast and copy every single element to a new array yourself; arrays are kind of stupid and don't fit the generics framework much ...

    kind regards,

    Jos

  5. #5
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default

    The Object comes from a third party API. That's why it is an array and not a List.

    Though, I don't see how a List makes it any easier. Instead of having an Object array (Object[]) with homogeneous items, it would be a List<Object> with homogeneous items. There is still the same problem of creating a typed List with the proper type.

  6. #6
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default

    Yes, down casting would be expensive. Is there another solution?
    Slow is better than not at all.

  7. #7
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,538
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by Thorton View Post
    Yes, down casting would be expensive. Is there another solution?
    Slow is better than not at all.
    Well you have to do it yourself in a very 'mechanical' way:

    Java Code:
    Object source[] = ...; // Assume they're all Strings
    String dest[]= new String[source.length];
    for (int i= 0; i < source.length; i++)
       dest[i]= (String)source[i]; // Cast and copy
    ... or you can play some tricks using the Arrays.asList and the List.toArray methods (which basically do the same as the snippet above).

    kind regards,

    Jos

  8. #8
    r035198x is offline Senior Member
    Join Date
    Aug 2009
    Posts
    2,388
    Rep Power
    8

    Default

    Quote Originally Posted by Thorton View Post
    ..

    Though, I don't see how a List makes it any easier. Instead of having an Object array (Object[]) with homogeneous items, it would be a List<Object> with homogeneous items. There is still the same problem of creating a typed List with the proper type.
    There would have been a big difference if you could use Lists because you can do
    Java Code:
    List<T> ts = new ArrayList<T>();
    but you cannot do T[] ts = new T[size];

  9. #9
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default

    Quote Originally Posted by r035198x View Post
    There would have been a big difference if you could use Lists because you can do
    Java Code:
    List<T> ts = new ArrayList<T>();
    but you cannot do T[] ts = new T[size];
    T is not known until run time.

    I'm afraid that I don't see how
    List<T> ts = new ArrayList<T>()
    can be done, but
    T[] ts = new T[size]
    cannot be done.

    If T is not known at compile time, neither are possible.
    If T is known at compile time, both are possible.
    Last edited by Thorton; 01-08-2010 at 10:00 PM.

  10. #10
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    Well you have to do it yourself in a very 'mechanical' way:

    Java Code:
    Object source[] = ...; // Assume they're all Strings
    String dest[]= new String[source.length];
    for (int i= 0; i < source.length; i++)
       dest[i]= (String)source[i]; // Cast and copy
    ... or you can play some tricks using the Arrays.asList and the List.toArray methods (which basically do the same as the snippet above).

    kind regards,

    Jos
    How is that different that what I originally posted (which was pointed out as being slow)?

  11. #11
    r035198x is offline Senior Member
    Join Date
    Aug 2009
    Posts
    2,388
    Rep Power
    8

    Default

    Quote Originally Posted by Thorton View Post
    T is not known until run time.

    I'm afraid that I don't see how
    List<T> ts = new ArrayList<T>()
    can be done, but
    T[] ts = new T[size]
    cannot be done.

    If T is not known at compile time, neither is possible.
    If T is known at compile time, both are possible.
    That's what we have been saying about generics not working well with arrays.
    Try those things yourself and see what happens.

  12. #12
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default

    Quote Originally Posted by r035198x View Post
    That's what we have been saying about generics not working well with arrays.
    Try those things yourself and see what happens.
    I'm Confused.

    What do you want me to try?
    I cannot come up with a situation where I can do List<T> but not T[] (as you mentioned).

  13. #13
    r035198x is offline Senior Member
    Join Date
    Aug 2009
    Posts
    2,388
    Rep Power
    8

    Default

    I am even more confused then.
    I have already given the examples!
    Do

    List<T> ts = new ArrayList<T>();
    T[] tserror = new T[5];

    In a class typed with T.
    The first compiles while the second does not.

  14. #14
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default

    Quote Originally Posted by r035198x View Post
    I am even more confused then.
    I have already given the examples!
    Do

    List<T> ts = new ArrayList<T>();
    T[] tserror = new T[5];

    In a class typed with T.
    The first compiles while the second does not.
    OK, I understand what you are saying now. I missed that the code was suppose to be inside a typed class. I was trying to figure out how to put that snipped in a simple main function.

    However, I'm not in a class typed with T. I could make one; though, the problem still remains that T is not known until run time and it is decided by a third party library. A typed/generic class cannot be created without knowing the type at compile time. If that could be done, I wouldn't need to create typed class and then create a List<T> inside it, I could just create the List with the appropriate type in the first place.

    This is a little confusing because of the situation I'm in. Let me explain more, though it may make it more confusing. I'm sitting between two third party libraries. The first gives me an object. I normally just pass that object on to the second library. Sometimes that object is an array of Objects (Object[]), but the Objects are of all the same type. In this case, the second library will cast it to the typed array that it wants. The typed array is that of the items in the Object array. But it cannot be known until run time. I need to create a typed array to pass to the last third party library, so that it doesn't choke when I pass it an Object[].

  15. #15
    r035198x is offline Senior Member
    Join Date
    Aug 2009
    Posts
    2,388
    Rep Power
    8

    Default

    I don't see the need to pass a typed array at all. There will be no difference in behavior whether you passed a typed array or an Object array. In fact if you did have a typed array the type would get erased before the code reaches the run time anyway.
    What do you hope to achieve by casting to a special type?

  16. #16
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,538
    Blog Entries
    7
    Rep Power
    20

    Default

    Don't tell them I told you but the following little rascal copies an array to a properly typed array. If the array is empty no component type can be found other than the orginal array component type so the original array will be returned.

    Java Code:
    Object copyOf(Object array) {
    		
    	int length= Array.getLength(array);
    		
    	if (length == 0) return array; // can't determine an element type.
    		
    	Class t= Array.get(array, 0).getClass(); // type of first component.
    
    	Object copy= Array.newInstance(t, length); // get a new array T[]
    		
    	for (int i= 0; i < length; i++)
    		Array.set(copy, i, Array.get(array, i));
    		
    	return copy;
    }
    kind regards,

    Jos

  17. #17
    AndreB's Avatar
    AndreB is offline Senior Member
    Join Date
    Dec 2009
    Location
    Stuttgart, Germany
    Posts
    114
    Rep Power
    0

    Default

    Maybe this could help. Or did i understand your problem wrong?
    Java Code:
    	public static void main(String[] args) {
    		Object[] someObjects = new Object[30];
    		Random r = new Random();
    		int someInt = r.nextInt(3);
    		for (int i = 0; i < someObjects.length; i++) {
    			switch (someInt) {
    			case 0:
    				someObjects[i] = new Integer(345);
    				break;
    			case 1:
    				someObjects[i] = new Double(243.6d);
    				break;
    			case 2:
    				someObjects[i] = new Object();
    				break;
    			default:
    				someObjects[i] = new Object();
    			}
    		}
    		
    		for (int i = 0; i < someObjects.length; i++) {
    			if (someObjects[i] instanceof Integer) {
    				System.out.println("yay some int !");
    			} else if (someObjects[i] instanceof Double) {
    				System.out.println("yay some double");
    			} else {
    				System.out.println("and so forth");
    			}
    		}
    	}
    "There is no foolproof thing; fools are too smart."
    "Why can't you solve my Problem ?"

  18. #18
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,538
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by AndreB View Post
    Maybe this could help. Or did i understand your problem wrong?
    According to the OP the types of all the array elements are supposed to be the same.

    kind regards,

    Jos

  19. #19
    Thorton is offline Member
    Join Date
    Jan 2010
    Posts
    15
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    Don't tell them I told you but the following little rascal copies an array to a properly typed array. If the array is empty no component type can be found other than the orginal array component type so the original array will be returned.

    Java Code:
    Object copyOf(Object array) {
    		
    	int length= Array.getLength(array);
    		
    	if (length == 0) return array; // can't determine an element type.
    		
    	Class t= Array.get(array, 0).getClass(); // type of first component.
    
    	Object copy= Array.newInstance(t, length); // get a new array T[]
    		
    	for (int i= 0; i < length; i++)
    		Array.set(copy, i, Array.get(array, i));
    		
    	return copy;
    }
    kind regards,

    Jos
    Very nice. Exactly what I needed.
    Array.newInstance was the critical piece I was missing.

    Thanks!

  20. #20
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,538
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by Thorton View Post
    Very nice. Exactly what I needed.
    Array.newInstance was the critical piece I was missing.

    Thanks!
    You're welcome of course but please realize that reflection is just a dirty cheat, it's like surgery and bypassing everything that is sane in Java.

    kind regards,

    Jos

Page 1 of 2 12 LastLast

Similar Threads

  1. Casting
    By zzpprk in forum Advanced Java
    Replies: 13
    Last Post: 08-13-2009, 07:59 PM
  2. What does casting mean?
    By sev51 in forum New To Java
    Replies: 3
    Last Post: 01-27-2009, 04:31 PM
  3. casting help
    By soc86 in forum New To Java
    Replies: 4
    Last Post: 01-13-2009, 11:07 PM
  4. Casting an int value into a char
    By kurtulas in forum New To Java
    Replies: 2
    Last Post: 02-16-2008, 08:03 PM
  5. Casting
    By leebee in forum New To Java
    Replies: 5
    Last Post: 08-10-2007, 12:24 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •