Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Generics Inheritance

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:

  • change the return value in the interface from Class<T> to Class<?>
  • change the class signature of OctreeMarshaller to public class OctreeMarshaller implements DataMarshaller<Octree>
like image 336
Entrusc Avatar asked Oct 26 '13 13:10

Entrusc


People also ask

Can generic be used with inheritance?

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.

Can we extend generic class in Java?

Yes, you can use any valid Java identifier for type parameters.

Is it a good idea to use generics in collections?

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.

What is Java generics with examples?

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.


2 Answers

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;
    }

    [...]
}
like image 139
Johannes Weiss Avatar answered Sep 29 '22 07:09

Johannes Weiss


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.

like image 24
Bohemian Avatar answered Sep 29 '22 06:09

Bohemian