<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: I'm glad that static typing is there to help...  </title>
    <link>http://blog.objectmentor.com/articles/2008/10/25/im-glad-that-static-typing-is-there-to-help</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>I'm glad that static typing is there to help...  </title>
      <description>&lt;h2&gt;The Background&lt;/h2&gt;
A colleague was using &lt;a hlink="http://www.fitnesse.org/"&gt;FitNesse&lt;/a&gt; to create a general fixture for setting values in various objects rendered from a &lt;span class="caps"&gt;DTD&lt;/span&gt;. Of course you can write one per top level object, but given the number of eventual end-points, this would require a bit too much manual coding.

	&lt;p&gt;This sounds like a candidate for reflection, correct? Yep, but rather than do that manually, using the &lt;a href="http://commons.apache.org/beanutils/"&gt;Jakarta Commons BeanUtils&lt;/a&gt; makes sense &amp;#8211; it&amp;#8217;s a pretty handy library to be familiar with if you&amp;#8217;re ever doing reflective programming with attributes.&lt;/p&gt;


So far, so good. However, the auto-generated classes included one-to-many relationships represented with arrays. Before getting any further, let&amp;#8217;s define this problem (at least partially) with a test: 
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
package com.objectmentor.arraycopyexample;

import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class ArrayPropertySetterTest {
   @Test
   public void assertCanAssignToArrayFieldFromArrayOfObject() {
      Object[] arrayOfBars = createArrayOfBars();
      Foo foo = new Foo();

      ArrayPropertySetter.assignToArrayFieldFromObjectArray(foo, "bars", arrayOfBars);

      assertEquals(3, foo.getBars().length);
   }

   private Object[] createArrayOfBars() {
      Object[] objectArray = new Object[3];
      for (int i = 0; i &amp;lt; objectArray.length; ++i)
         objectArray[i] = new Bar();

      return objectArray;
   }
}
&lt;/pre&gt;

For completeness, you&amp;#8217;ll need to see the Foo and Bar classes:
&lt;h3&gt;Bar&lt;/h3&gt;
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
package com.objectmentor.arraycopyexample;

public class Bar {
}
&lt;/pre&gt;

&lt;h3&gt;Foo&lt;/h3&gt;
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;;"&gt;
package com.objectmentor.arraycopyexample;

public class Foo {
    Bar[] bars;

    public Bar[] getBars() {
        return bars;
    }

    public void setBars(Bar[] bars) {
        this.bars = bars;
    }

}
&lt;/pre&gt;

	&lt;p&gt;So an instance of a Foo holds on to an array of Bar objects; and the Foo class has the standard java-bean-esque setters and getters.&lt;/p&gt;


	&lt;p&gt;With this description of how to set an array field on a Java bean, let&amp;#8217;s get this to actually work.&lt;/p&gt;


First question, how do you deal with arrays in Java? Sounds trivial, right. If you don&amp;#8217;t mind a little pain, it&amp;#8217;s not that bad&amp;#8230; By dealing, I mean what happens when someone has given you an array created as follows:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   Object[] arrayOfObject = new Object[3]:
&lt;/pre&gt;

Note that this is very different from this:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   Object[] arrayOfBars = new Bar[3]:
&lt;/pre&gt;

	&lt;p&gt;The runtime type of these two results is different. One is array of Object; the other is Array of Bar.&lt;/p&gt;


This will not work:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   Bar[] arrayOfBar = (Bar[])arrayOfObject;
&lt;/pre&gt;

This will generate a runtime cast exception. You cannot simply take something allocated as an array of objects and cast it to an array of a specific type. NO, you have to do something more like the following:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
    Array.newInstance(typeYouWantAnArrayOf, sizeOfArray);
&lt;/pre&gt;

	&lt;p&gt;That&amp;#8217;s not too bad, right? You can then either use another method on the Array class to set the values, or you can cast the result to an appropriate array.&lt;/p&gt;


That&amp;#8217;s enough information to write a generic method to copy from an array of Object to an array of a subtype of Object:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   public static Object[] copyToArrayOfType(Class destinationType, Object[] fromArray) {
      Object[] result = (Object[])Array.newInstance(destinationType, fromArray.length);

      for(int i = 0; i &amp;lt; fromArray.length; ++i)
         result[i] = fromArray[i];

      return result;
   }
&lt;/pre&gt;

This is a bit unruly because the caller still needs to cast the result:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   Object[] arrayOfObject = new Object[] { new Foo(), new Foo(), new Foo() };
   Foo[] arrayOfFoo = (Foo[])copyToArrayOfType(Foo.class, arrayOfObject);
&lt;/pre&gt;

We can get rid of this cast if we use generics:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   public static &amp;lt;T&amp;gt; T[] copyToArrayOfType(Class&amp;lt;T&amp;gt; destinationType, Object[] fromArray) {
      T[] result = (T[])Array.newInstance(destinationType, fromArray.length);

      for(int i = 0; i &amp;lt; fromArray.length; ++i)
         result[i] = (T) fromArray[i];

      return result;
   }
&lt;/pre&gt;

This doesn&amp;#8217;t quite work because of type erasure, so to get this to &amp;#8220;compile cleanly &amp;#8211; no warnings&amp;#8221;, you&amp;#8217;ll need to add the following line above the method:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   @SuppressWarnings("unchecked")
&lt;/pre&gt;

	&lt;p&gt;That&amp;#8217;s just me telling the compiler I really think I know what I&amp;#8217;m doing.&lt;/p&gt;


With this change, you can now write the following:
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   Object[] arrayOfObject = new Object[] { new Foo(), new Foo(), new Foo() };
   Foo[] arrayOfFoo = copyToArrayOfType(Foo.class, arrayOfObject);
&lt;/pre&gt;

	&lt;p&gt;The original problem was to take an array of Object[] and set it into a destination object&amp;#8217;s attribute. Now we can create an array with the correct type, what next?&lt;/p&gt;


There are several things still remaining:
&lt;ol&gt;
   &lt;li&gt;Given the name of the property, determine its underlying array type.&lt;/li&gt;
   &lt;li&gt;Create the array (above)&lt;/li&gt;
   &lt;li&gt;Assign the value to the underlying field&lt;/li&gt;
   &lt;li&gt;Do some suficient hand-waving to handle exceptions&lt;/li&gt;
&lt;/ol&gt;

	&lt;p&gt;Here are solutions for each of those things:&lt;br/&gt;
&lt;b&gt;Determine underlying type&lt;/b&gt;
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor( destObject, fieldName);
   Class&amp;lt;?&amp;gt; destType = pd.getPropertyType().getComponentType();
&lt;/pre&gt;&lt;/p&gt;


	&lt;p&gt;&lt;b&gt;Create the array&lt;/b&gt;
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   Object[] destArray = copyToArrayOfType.(destType, fromArray);
&lt;/pre&gt;&lt;/p&gt;


&lt;B&gt;Assign the value&lt;/b&gt;
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   PropertyUtils.setSimpleProperty(destObject, fieldName, destArray);
&lt;/pre&gt;

Here&amp;#8217;s all of that put together and simply capturing all of the checked exceptions (that&amp;#8217;s a whole other can of worms):
&lt;pre style="line-height: 1em; background-color: #d8d5c3; border: 1px solid #888;;"&gt;
   public static void assignToArrayFieldFromObjectArray(Object destObject, String fieldName, Object[] fromArray) {
      try {
         PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(destObject, fieldName);
         Class&amp;lt;?&amp;gt; destType = pd.getPropertyType().getComponentType();
         Object[] destArray = copyToArrayOfType(destType, fromArray);
         PropertyUtils.setSimpleProperty(destObject, fieldName, destArray);
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
   }
&lt;/pre&gt;

	&lt;p&gt;That&amp;#8217;s all it takes to copy an array and then set the value in the field of a destination object.&lt;/p&gt;


	&lt;p&gt;Simple, right?&lt;/p&gt;


	&lt;p&gt;Sometimes static (and strong) typing can get in the way. This is one of those cases. Luckily, you can write this one and use it all over. Maybe it&amp;#8217;s a part of the BeanUtils that I was unable to track down (probably).&lt;/p&gt;</description>
      <pubDate>Sat, 25 Oct 2008 05:24:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:ca4fa4d0-1f85-4f16-9e5e-4b517e015f3e</guid>
      <author>Brett Schuchert</author>
      <link>http://blog.objectmentor.com/articles/2008/10/25/im-glad-that-static-typing-is-there-to-help</link>
      <category>Schuchert's Scattered Synapses </category>
      <category>reflection</category>
      <category>beanutils</category>
      <category>FitNesse</category>
      <category>Java</category>
      <category>rant</category>
    </item>
    <item>
      <title>"I'm glad that static typing is there to help...  " by Greg M</title>
      <description>&lt;p&gt;Yeah, Java has a pretty sorry excuse for a static type system. The sort of thing that&amp;#8217;d be a breeze in any modern language. (in many languages that predate Java 1.0, even)&lt;/p&gt;</description>
      <pubDate>Tue, 28 Oct 2008 02:42:33 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:71a00a88-9afa-48dc-8082-03c6c576d5c3</guid>
      <link>http://blog.objectmentor.com/articles/2008/10/25/im-glad-that-static-typing-is-there-to-help#comment-2145</link>
    </item>
    <item>
      <title>"I'm glad that static typing is there to help...  " by Paul Holser</title>
      <description>&lt;p&gt;Yeah, cool, that @SuppressWarnings&amp;#8230;&lt;a href="http://cleveralias.blogs.com/thought_spearmints/2006/01/suppresswarning.html" rel="nofollow"&gt;http://cleveralias.blogs.com/thought_spearmints/2006/01/suppresswarning.html&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 27 Oct 2008 00:56:55 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:6be68137-ac5c-4dae-91e2-54f10ae34921</guid>
      <link>http://blog.objectmentor.com/articles/2008/10/25/im-glad-that-static-typing-is-there-to-help#comment-2144</link>
    </item>
    <item>
      <title>"I'm glad that static typing is there to help...  " by Brett L. Schuchert</title>
      <description>&lt;p&gt;Thanks Paul. For some reason, I had it in my mind that the Suppress Warnings annotation&amp;#8217;s target was  a method.&lt;/p&gt;


	&lt;p&gt;However, adding it to a declaration line is very smart. You&amp;#8217;re cooking with gas!&lt;/p&gt;</description>
      <pubDate>Sun, 26 Oct 2008 14:27:18 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:66902c86-e4d4-4996-8bc9-bc3253ef5e8d</guid>
      <link>http://blog.objectmentor.com/articles/2008/10/25/im-glad-that-static-typing-is-there-to-help#comment-2143</link>
    </item>
    <item>
      <title>"I'm glad that static typing is there to help...  " by Paul Holser</title>
      <description>&lt;p&gt;You can eliminate one warning and push the suppression closer to the cause in copyToArrayOfType() like so:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;public static  T[] copyToArrayOfType(Class destinationType, Object[] fromArray) {
    @SuppressWarnings("unchecked")
    T[] result = (T[]) Array.newInstance(destinationType, fromArray.length);
    for (int i = 0; i &amp;lt; fromArray.length; ++i)
       result[i] = destinationType.cast(fromArray[i]);
    return result;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Sun, 26 Oct 2008 14:04:30 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:d5e1f18a-2302-41fa-ae37-3d521c67e706</guid>
      <link>http://blog.objectmentor.com/articles/2008/10/25/im-glad-that-static-typing-is-there-to-help#comment-2142</link>
    </item>
  </channel>
</rss>
