1

In some Java code I have an interface like this:

interface A<T> {
    T produce();
    compare(T x, T y);
}

I have different implementations, such as:

class B extends A<int[]> {
    int[] produce() {...}
    compare(int[] x, int[] y) {...}
}

The issue is how to capture the implementation specific generic type. The following doesn't work:

A<T> a = new B();
T x = a.produce();
T y = a.produce();
a.compare(x, y);

Because of course the type T does not refer to what's inside B. (In fact it doesn't refer to anything.)

Is there a way to make T capture the generic type of B?

Thomas Ahle
  • 30,774
  • 21
  • 92
  • 114
  • 3
    You already know it's `int[]`, why do you want a generic variable? – Sotirios Delimanolis Mar 27 '15 at 15:31
  • Sadly, Java is missing an identifier to let the compiler infer the type, like `auto` in C++ or `var` in C#, and there's no good way to keep this general other than calling `compare` in a single line (except Reflection) – Binkan Salaryman Mar 27 '15 at 15:36
  • 1
    Sotirios : Other implementations may use different types. – Thomas Ahle Mar 27 '15 at 15:39
  • And they will still know. If you're writing `new B()` in your source code, you know that the generic type argument for `A` is `int[]`. Maybe your example is not indicative of what you are trying to do. – Sotirios Delimanolis Mar 27 '15 at 15:41
  • 1
    @SotiriosDelimanolis: If the assumption in my answer is correct, I think in the real world the instantiation of `a` and the subsequent operations would be separated. – Mark Peters Mar 27 '15 at 15:42

1 Answers1

2

If I can read between the lines a bit, I think what you are asking is how do you make this part in particular generic:

T x = a.produce();
T y = a.produce();
a.compare(x, y);

The answer is usually to "bind" the type parameter using a generic method:

private static <T> void produceAndCompare(A<T> a) {
    T x = a.produce();
    T y = a.produce();
    a.compare(x, y);
}

Then you can call it like this:

produceAndCompare(new B());

And if it needs to be in a variable first:

A<?> a = getSomeA(); //could just return new B();
produceAndCompare(a);
Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • Ah, so you "take advantage" of the methods ability to bind generics. Interesting. – Thomas Ahle Mar 27 '15 at 18:41
  • @ThomasAhle: Exactly. I gave a more detailed explanation in this answer: http://stackoverflow.com/questions/16449799/how-do-generics-of-generics-work/16451216#16451216. Also, this Java tutorial goes into this topic fairly well: http://docs.oracle.com/javase/tutorial/java/generics/capture.html – Mark Peters Mar 27 '15 at 18:50
  • It still seems strange that the only way to declare and capture a generic type, is in method definitions. If the functionality is already in Java, may there not be a way to capture the type inside the actual code? – Thomas Ahle Mar 28 '15 at 13:00
  • 1
    @ThomasAhle: I agree, it would be pretty straightforward for them to have added this to the language. However, I use generics extensively in the real world, and I could count on one hand the number of times where I wanted this, but thought that a helper method would have been inappropriate. So perhaps it's justified to not bloat the language with the feature. – Mark Peters Mar 28 '15 at 17:24