dcsimg
Collection classes in Java aren't template classes - a workaround (part 3)
2 posts in topic
Flat View  Flat View
TOPIC ACTIONS:
 

Posted By:   Jon_Thorarinsson
Posted On:   Monday, March 4, 2002 07:18 AM

More on the previous discussion: Here's a "type-safe template" Map class for Java: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - package com.myCompany.johnny.utils; import java.util.HashMap; import java.util.Iterator; import java.util.Map; // Map from Integer objects to Car objects. // The type-safe-insertion version. // use: Integer2Car_Map map = new Integer2Car_HashMap(); interface Integer2Car_Map extends Map{} class Integer2Car_HashMap extends THashMap implements Integer2Car_Map {     Integer2Car   More>>

More on the previous discussion: Here's a "type-safe template" Map class for Java:


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


package com.myCompany.johnny.utils;


import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;


// Map from Integer objects to Car objects.

// The type-safe-insertion version.

// use: Integer2Car_Map map = new Integer2Car_HashMap();

interface Integer2Car_Map extends Map{}

class Integer2Car_HashMap extends THashMap implements
Integer2Car_Map

{

    Integer2Car_HashMap()

    {

          super (Integer. class , Car. class );

    }

}


// A type safe HashMap

public class THashMap extends HashMap

{

    // This is what makes the class "type-safe".

     private Class mKeyClass, mValueClass;


     private boolean mapContainsWrongTypes(Map c)

    {

         Map.Entry tmp;

          for (Iterator it = c.entrySet().iterator(); it.hasNext();)

         {

              tmp = (Map.Entry)it.next();

               if (!mKeyClass.isInstance(tmp.getKey()))

              {

                    return true ;

              }


               if (!mValueClass.isInstance(tmp.getValue()))

              {

                    return true ;

              }

         }


          return false ;

    }


     public THashMap(Class elementTemplateKey, Class elementTemplateValue)

    {

         mKeyClass = elementTemplateKey;

         mValueClass = elementTemplateValue;

    }


    // Override the 2 insertion methods of the Map interface:

     public Object put(Object key, Object value)

    {

          if (!mKeyClass.isInstance(key))

         {

               throw new ClassCastException();

         }


          if (!mValueClass.isInstance(value))

         {

               throw new ClassCastException();

         }


          return super.put(key, value);

    }


     public void putAll(Map t)

    {

          if (mapContainsWrongTypes(t))

         {

               throw new ClassCastException();

         }


          super .putAll(t);

    }


    // A simple test of the class

     public static void main(String[] args)

    {

         // See definition of Integer2Car_Map and Integer2Car_HashMap

         // at the bottom of the file

         Integer2Car_Map map = new Integer2Car_HashMap();


          try

         {

              map.put( new Integer(0), new Car("Volvo"));    // correct type


              map.put( new Integer(1), new Integer(2));     // should throw, because

              map.put( new Car(), new Integer(3));    // an incorrect type is being

              map.put( new String(), new String());     // inserted

         }

          catch (ClassCastException e)

         {

              System.out.println("good");

         }


         Car tmp = new Car("Volvo");

          if (((Car)map.get( new Integer(0))).equals(tmp))

         {

              System.out.println("good");

         }

          else

         {

              System.out.println("bad");

         }


         foo(map);

    }


    // An example of passing an Integer2Car_Map as a

    // parameter to a method. It's obvious from

    // the typename of the parameter that this

    // is a Map from Integer objects to Car objects

     private static void foo(Integer2Car_Map map)

    {

         // Test the putAll() method. Create a Map and insert

         // one correct item and one incorrect item

         Map m = new HashMap();


         // The correct item. The value here will be a

         // subclass of Car, just for testing if that works

         // (it does)

         m.put(

               new Integer(4),

               new Car("Ferrari")

              {

                    void drive()

                   {

                        System.out.println("driving a " + getStr() + " really fast");

                   }

              }

         );


         // The incorrect item

         m.put( new Integer(5), new Integer(6));


          try

         {

              map.putAll(m); // should throw, because an

                                  // incorrect type is being inserted

                                  // (the second item inserted in 'm')

         }

          catch (ClassCastException e)

         {

              System.out.println("good");

         }

    }

}


class Car

{

     private String mStr = new String();


    Car()

    {

    }


    Car(String str)

    {

         mStr = str;

    }


    String getStr()

    {

          return mStr;

    }


     void drive()

    {

         System.out.println("driving a " + mStr);

    }


     public boolean equals(Object obj)

    {

          return obj instanceof Car && ((Car)obj).mStr.equals(mStr) ? true : false ;

    }

}

   <<Less

Re: Collection classes in Java aren't template classes - a workaround (part 3)

Posted By:   Duncan_Forster  
Posted On:   Tuesday, March 5, 2002 01:53 AM

From answer to part 2:

Yes, there already is an alternative solution. Check out JSR-014. It uses the same format as C++ (ie Vector x = new Vector()). It is basically a modified compiler that produces standard bytecode that is backward compatiable. Chech it out.

Re: Collection classes in Java aren't template classes - a workaround (part 3)

Posted By:   AlessandroA_Garbagnati  
Posted On:   Monday, March 4, 2002 07:30 AM

Jon,

May I ask you a question?


What's wrong with the possibility of adding a not heterogeneous set of classes inside a Collection (List/Map/Set)? I consider this an incredible power feature of the Collection API. Plus, reflection, or even the simple "instanceof", can help you in managing the content.

About | Sitemap | Contact