I have a situation where I need to store fields of differing types of some data structures along with some similar metadata (The application takes data from one of many sources, some data possibly coming from more than one source, and then does stuff with it).
The solution I came up with was to create a class that would hold each piece of data which I could then add to each object. The DataParam
object can be loaded with any data type that's determined when it's first constructed. When we get or set it later, those methods are passed a class type similar to what we are getting or setting. Since we always check against the value we originally "typed" our object with, we can never accidentally set it to some other type of value (and mess everything up).
The reason these are all generic methods and the entire class isn't a generic is because I need to store DataParam
in a container and that wouldn't be possible if the class itself was a generic (I can't store a DataParam<String>
, and a DataParam<int>
in one container).
public class DataParam
{
public String name
public boolean wasUpdated
private String type
private boolean isArray
private Object data;
public <T> DataParam(String name, Class<T> typeClass)
{
this.name = name;
type = typeClass.getName();
isArray = typeClass.isArray();
data = null;
wasUpdate = false;
}
public <T> T get(Class<T> typeClass)
{
if(type.equals(typeClass.getName()) && isArray == typeClass.isArray())
return typeClass.cast(data);
else
return null;
}
public <T> T set(T obj, Class<T> typeClass)
{
if(type.equals(typeClass.getName()) && isArray == typeClass.isArray())
data = (Object) obj;
}
public String doSomething()
{
//An example of doing different things based on type
switch(type)
{
case "java.lang.String":
if(isArray)
return TakesAStringArray(get(String[].class));
else
return TakesAString(get(String.class));
break;
case "java.lang.Integer":
return TakesAnInteger(get(Integer.class));
break;
case "myPackage.DataParam":
return TakesADataParam(get(myPackage.DataParam.class));
break;
//default: Do nothing
}
}
public DataObj
{
protected HashMap<String,DataParam> fields;
//Other functions
}
public SpecificObj extends DataObj
{
public SpecificObj()
{
fields.add(new DataParam("name", String.class));
fields.add(new DataParam("obj", myPackage.DataParam.class));
fields.add(new DataParam("count", Integer.class));
}
}
My questions are, is there anything blatantly obviously wrong with this, like I'm gonna screw myself over later? Is there a better way that I should consider?
This should be type safe, right? (I'm checking the class every time I do anything with that piece of data, but it just seems weird that I have to do it myself versus like, the compiler raising an error that I'm doing it wrong).