Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have a map that only allows value types based on the key?

Tags:

java

I know this sounds a little crazy but here it is. I have an enum type that represents represents a bunch of different properties. Each could be just a string but it would be nice to enforce some kind of type safety. So basically check the type associated with each enum value and throw an exception if there is a mismatch. I guess it could be done with instance of but I am curious if there is another way to do this without instanceof. I know that may not be possible but I am curious.

Edit, I created a new example that I think illustrates what I am asking better:

public class CmisProperties {

    public enum CmisPropEnum{
        Name (PropertyIds.NAME, new String() ),
        CreatedBy (PropertyIds.CREATED_BY, new String()  ),
        CreationDate (PropertyIds.CREATION_DATE, new Date() ),
        LastModifiedBy (PropertyIds.LAST_MODIFIED_BY, new String() ),
        LastModificationDate (PropertyIds.LAST_MODIFICATION_DATE, new Date() ),
        ChangeToken (PropertyIds.CHANGE_TOKEN, new String()  );

            private String propId;

        CmisPropEnum ( String propId , Object templateObject ){
            this.propId = propId;
        }

        public <T> String getPropId(){
            return propId;
        }
    }

        private Map<CmisPropEnum, Object> propertyMap = new HashMap<CmisPropEnum, Object>();

    public Object getProperty(CmisPropEnum propEnum){
         return propertyMap.get(propEnum.getPropId());
    }

    public void setProperty( CmisPropEnum propEnum, Object value){
             propertyMap.put(propEnum, value);
    }
}

Later on I want this to happen:

CmisProperties props = new CmisProperties();
/* This causes a compile time exception */
props.setProperty(CmisPropEnum.CreationDate, "foobar" );
/* This I want to be ok, because the type matches that in the enum */
props.setProperty(CmisPropEnum.CreationDate, new Date() );
like image 301
startoftext Avatar asked Nov 04 '22 11:11

startoftext


1 Answers

Check out Josh Bloch's Effective Java, Item 29, where he describes a "typesafe heterogeneous container" that he calls Favorites. The API is

public class Favorites {
   public <T> void putFavorite(Class<T> type, T instance);
   public <T> T getFavorite(Class<T> type);
}

I think it would fit your needs (probably change the name???). You could call

favorite.putFavorite(Name.getClass(), "Fred");
favorite.putFavorite(ADate.getClass(), new Date(1234));

and later

Date date = favorite.getFavorite(ADate.getClass());
like image 178
user949300 Avatar answered Nov 15 '22 12:11

user949300