patternjavaMinor
Typesafe heterogeneous container
Viewed 0 times
containerheterogeneoustypesafe
Problem
I was reading Joshua Blochs "Effective Java 2nd edition" item 29, which describes how to create Heterogeneous containers, in the end of chapter he wrote:
A Class object used in this fashion is called a type token. You can
also use a custom key type. For example, you could have a DatabaseRow
type representing a database row (the container), and a generic type
Column as its key.
It wondered me and I wrote this implementation which he has mentioned. Is there something I could have done better ? I'm mostly interested in
A Class object used in this fashion is called a type token. You can
also use a custom key type. For example, you could have a DatabaseRow
type representing a database row (the container), and a generic type
Column as its key.
It wondered me and I wrote this implementation which he has mentioned. Is there something I could have done better ? I'm mostly interested in
Column class which serves as Type Tokenclass Column {
@SuppressWarnings("unchecked")
public T cast(Object obj) {
return (T) obj;
}
}
public class DatabaseRow {
private Map, Object> row = new HashMap<>();
public void putColumn(Column type, T instance) {
row.put(type, type.cast(instance));
}
public T getColumn(Column type) {
return type.cast(row.get(type));
}
public static void main(String[] args) {
DatabaseRow db = new DatabaseRow();
Column colInt = new Column<>();
Column colDouble = new Column<>();
db.putColumn(colInt, 1);
db.putColumn(colDouble, 10.0);
System.out.println(colInt.getClass() + " " + colDouble.getClass());
System.out.println(db.getColumn(colInt) + " " + db.getColumn(colDouble));
}
}Solution
There are two things I would like to point out here.
-
There is no need to do the cast on the
-
The Column's cast method would be better done using a
this has the benefit of not requiring the SuppressWarnings. It also ends up being helpful for other reasons too.
The class would be used as:
Apart from that, things will be the same.
-
There is no need to do the cast on the
putColumn call. The method signature is: public void putColumn(Column type, T instance) { so we know that instance is of type T already, and it is being stored in an Object value in a Map. There is no reason to force the cast before storing it.-
The Column's cast method would be better done using a
Class instance. Consider the 'standard' pattern of requiring a class instance in the constructor of the Column. For example:class Column {
private final Class valClass;
public Column(Class valClass) {
this.valClass = valClass;
}
public T cast(Object obj) {
return obj == null ? null : valClass.cast(obj);
}
}this has the benefit of not requiring the SuppressWarnings. It also ends up being helpful for other reasons too.
The class would be used as:
Column col = new Column(String.class);Apart from that, things will be the same.
Code Snippets
class Column<T> {
private final Class<T> valClass;
public Column(Class<T> valClass) {
this.valClass = valClass;
}
public T cast(Object obj) {
return obj == null ? null : valClass.cast(obj);
}
}Column<String> col = new Column(String.class);Context
StackExchange Code Review Q#55737, answer score: 4
Revisions (0)
No revisions yet.