I have the following interface for a marshaller that marshalls an Object
to a DataNode
object and back:
public interface DataMarshaller<T> {
/**
* returns the actual class that this marshaller is capable of marshalling.
* @return
*/
Class<T> getDataClass();
/**
* marshalls the object to a DataNode
*
* @param object
* @return
*/
DataNode marshal(T object);
/**
* unmarshalls the object from a DataNode
*
* @param node
* @return
*/
T unMarshal(DataNode node);
}
To make sure that I'm able to get the correct marshaller for an object I also have the method Class<T> getDataClass()
that returns its class (that would have been lost after compiling because of type erasure).
Now I wanted to implement this interface in a class that is able to marshal objects of type Octree<T>
like this:
public class OctreeMarshaller<T> implements DataMarshaller<Octree<T>> {
@Override
public Class<Octree<T>> getDataClass() {
return Octree.class; //<- compiletime error
}
@Override
public DataNode marshal(Octree<T> object) {
//...
}
@Override
public Octree<T> unMarshal(DataNode node) {
//...
}
}
My problem is now that (of course) Octree.class
is not of type Class<Octree<T>>
but rather of the non generic type Class<Octree>
and Java won't allow me to cast it to Class<Octree<T>>
.
The question is now: is there a more elegent way to solve that than the two I already considered:
Class<T>
to Class<?>
OctreeMarshaller
to public class OctreeMarshaller implements DataMarshaller<Octree>
Generics also provide type safety (ensuring that an operation is being performed on the right type of data before executing that operation). Hierarchical classifications are allowed by Inheritance. Superclass is a class that is inherited. The subclass is a class that does inherit.
Yes, you can use any valid Java identifier for type parameters.
By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.
Generics add that type of safety feature. We will discuss that type of safety feature in later examples. Generics in Java are similar to templates in C++. For example, classes like HashSet, ArrayList, HashMap, etc., use generics very well.
Without an instance of Octree<T>
you cannot construct a class object of type Class<Octree<T>>
. But since we know (due to type erasure) there is only one class Octree
during run time, it's safe to write
public class OctreeMarshaller<T> implements DataMarshaller<Octree<T>> {
@Override
@SuppressWarnings("unchecked")
public Class<Octree<T>> getDataClass() {
return (Class<Octree<T>>)(Class<?>)Octree.class;
}
[...]
}
With Class
of a generic type, you need a double cast:
public Class<Octree<T>> getDataClass() {
return (Class<Octree<T>>)(Class<?>)Octree.class;
}
Whacky, but it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With