patternjavaMinor
Pattern for storing object of varying type
Viewed 0 times
varyingtypeforobjectstoringpattern
Problem
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
The reason these are all generic methods and the entire class isn't a generic is because I need to store
```
public class DataParam
{
public String name
public boolean wasUpdated
private String type
private boolean isArray
private Object data;
public DataParam(String name, Class typeClass)
{
this.name = name;
type = typeClass.getName();
isArray = typeClass.isArray();
data = null;
wasUpdate = false;
}
public T get(Class typeClass)
{
if(type.equals(typeClass.getName()) && isArray == typeClass.isArray())
return typeClass.cast(data);
else
return null;
}
public T set(T obj, Class 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 TakesAStringArra
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, and a DataParam in one container).```
public class DataParam
{
public String name
public boolean wasUpdated
private String type
private boolean isArray
private Object data;
public DataParam(String name, Class typeClass)
{
this.name = name;
type = typeClass.getName();
isArray = typeClass.isArray();
data = null;
wasUpdate = false;
}
public T get(Class typeClass)
{
if(type.equals(typeClass.getName()) && isArray == typeClass.isArray())
return typeClass.cast(data);
else
return null;
}
public T set(T obj, Class 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 TakesAStringArra
Solution
What you are doing appears to be sane. The use of generics is primarily as a compile-time validator (and it makes some code simpler, like not having to cast things).
If you don't know the types of your data at compile time, then you can't use generics.
So, you have run-time specified data, and that's OK. Do you handle that as well as it can be handled? That is the real question.
Items I can see that raise question-marks:
Edit: with Class saved instead of name and isArray
Also, I note now that you are missing some semi-colons in your data declarations.... and also, you are missing return values from some of your methods.
If you don't know the types of your data at compile time, then you can't use generics.
So, you have run-time specified data, and that's OK. Do you handle that as well as it can be handled? That is the real question.
Items I can see that raise question-marks:
- Why are you saving away the Class name (as
type) when you can save away the actual Class?
wasUpdatedis not used.
typeis a bad name for a Java variable. It conflicts withjava.lang.Type, and you don't need it anyway if you are going to store the Class instead of its name.
- if you do keep the class, then you can use the
Class.isInstance(...)method to ensure the data types are correct, instead of specifying the class as part of the retrieval in theget(Class clazz)method... or, you can confirm they are the same with a simple.equals()call instead of the name/isArray check.
- the methods like
return TakesAnInteger(...)should have a lower-casetto start with.... this is the Java convention for method names.
- Similarly, Java convention is to put the opening brace
{for a block on the same line as the method declaration.
Edit: with Class saved instead of name and isArray
Also, I note now that you are missing some semi-colons in your data declarations.... and also, you are missing return values from some of your methods.
public class DataParam {
public String name;
public Class dataClass;
public boolean wasUpdated;
private Object data;
public DataParam(String name, Class typeClass) {
this.name = name;
dataClass = typeClass;
data = null;
wasUpdated = false;
}
public T get(Class typeClass) {
if(dataClass.equals(typeClass)) {
return typeClass.cast(data);
}
return null;
}
public T set(T obj, Class typeClass) {
if(dataClass.equals(typeClass)) {
T toreturn = typeClass.cast(data);
data = obj;
return toreturn;
}
return null;
}
public String doSomething() {
//An example of doing different things based on type
//.......
return null;
}
}Code Snippets
public class DataParam {
public String name;
public Class<?> dataClass;
public boolean wasUpdated;
private Object data;
public DataParam(String name, Class<?> typeClass) {
this.name = name;
dataClass = typeClass;
data = null;
wasUpdated = false;
}
public <T> T get(Class<T> typeClass) {
if(dataClass.equals(typeClass)) {
return typeClass.cast(data);
}
return null;
}
public <T> T set(T obj, Class<T> typeClass) {
if(dataClass.equals(typeClass)) {
T toreturn = typeClass.cast(data);
data = obj;
return toreturn;
}
return null;
}
public String doSomething() {
//An example of doing different things based on type
//.......
return null;
}
}Context
StackExchange Code Review Q#44216, answer score: 6
Revisions (0)
No revisions yet.