Reputation: 16901
I'm trying to wrap (and simplify) the MapDB library in my project like this:
public class MapDbPersistentStorage<V> { private DB db; private HTreeMap<String, V> storage; public MapDbPersistentStorage(String filename) { db = DBMaker .fileDB(filename) .fileMmapEnable() .make(); storage = (HTreeMap<String, V>) db .hashMap("section", Serializer.STRING, Serializer.LONG) .createOrOpen(); } public V get(String key, V defaultValue) { return storage.getOrDefault(key, defaultValue); } public void set(String key, V value) { storage.put(key, value); } public void close() { db.close(); } }
As it's been pointed out, the problem is the Serializer.LONG
part (it's supposed to be of type V
). I need to come up with a serializer based on the generic type provided. What's the right way to do so?
Upvotes: 0
Views: 369
Reputation: 33895
Java uses erasure to implement it's generics. At runtime, your class has no idea what V
you used to instantiate it with. That information is not retained at runtime.
So if you need it at runtime, you're going to have to manually retain it. But in your current program, the compiler has no idea how the type Long
should relate to Serailizer.Long
.
To be (somewhat) typesafe, you could wrap the Serializer
in a generic class or interface which generic type corresponds to the type encoded by the serialzer. Effectively provide a way to link the 2 type systems.
interface GenericSerializer<T> extends Supplier<Serializer> {
public static GenericSerializer<Long> ofLong() {
return () -> Serializer.Long;
}
...
}
Then in your class:
public class MapDbPersistentStorage<V> {
private DB db;
private HTreeMap<String, V> storage;
private final Serializer ser;
public MapDbPersistentStorage(GenericSerializer<V> serFactory) {
this.ser = serFactory.get();
}
public MapDbPersistentStorage(String filename) {
db = DBMaker
.fileDB(filename)
.fileMmapEnable()
.make();
storage = (HTreeMap<String, V>) db
.hashMap("section", Serializer.STRING, ser)
.createOrOpen();
}
...
}
Usage:
MapDbPersistentStorage<Long> m = new MapDbPersistentStorage<>(GenericSerializer.ofLong());
Where the compiler can check that the type of the GenericSerializer
corresponds to that of the MapDbPersistentStorage
.
Upvotes: 1