10.28.2011

Java Problem: Generic Inheritance and Calling GetMethod().getReturnType()

In my current project, I have classes which are modeled like the following. At some point, a method like getReturnTypeForGetId() is called on classes A and B. Calling the method with A returns Integer as expected, but B returns Serializable.

What am I missing here? Am I getting bitten by some heinous erasure thing, or am I just missing out on some sort of generic context-clobbering?

EDIT: Adding an over-ridden getId() method to B fixes the problem, but I would still like to understand what I am running into.

I've also asked this question on stackoverflow.

import java.io.Serializable;

public class WeirdTester {
    static interface Identifiable<T extends Serializable> {
        T getId();
        void setId(final T id);
    }

    static abstract class BaseEntity<T extends Serializable> implements Identifiable<T> {
        private T id;
        public T getId() { return id; }
        public void setId(final T id) { this.id = id; }
    }

    static class A implements Identifiable<Integer> {
        private Integer id;
        public Integer getId() { return id; }
        public void setId(final Integer id) { this.id = id; }
    }

    static class B extends BaseEntity<Integer> {}

    @SuppressWarnings("unchecked")
    private static <T extends Serializable, Q extends Identifiable<T>> Class<T> getReturnTypeForGetId(
            final Class<Q> clazz) throws Exception {
        return (Class<T>) clazz.getMethod("getId", (Class[])null).getReturnType();
    }

    public static void main(final String[] args) throws Exception {
        System.out.println(getReturnTypeForGetId(A.class));
        // CONSOLE: "class java.lang.Integer"
        System.out.println(getReturnTypeForGetId(B.class));
        // CONSOLE: "interface java.io.Serializable"
    }
}

No comments: