Skip to content
Advertisement

Workarounds to implement interface including , with X[] type parameter

Let’s say we have some interface like this:

public interface Foo<T> {

   <TIn extends T> void encode(TIn value)

   T decode()

}

I’m using Foo a lot in my codebase, but I wish to add the TIn extends T to make it more flexible, to eg have a Foo<Map<X>> able to encode a HashMap<X> or a TreeMap<X>.

This works really well – until I tried to implement Foo<T[]>, where it seems to be impossible to implement, with public <TIn extends TItem[]> void encode(TIn array) giving a parse error “> expected” when it hits the brackets []. Even IntelliJ does nothing when it volunteers to implement the interface.

For what it’s worth, if T is some other concrete final type (eg byte[], Boolean, etc), it seems that I can satisfy the interface by just returning T, so it seems to do some hidden intelligent fixing here. So it seems that it’s just a problem with T[] where it can’t detect T[] is final.

Does anyone have any ideas about how I can workaround this? I don’t really care that TIn extends byte[] can only be met with TIn = byte[], I just want to implement the interface for the compiler to be happy; and so that this interface can be used elsewhere.

Advertisement

Answer

None of this makes sense. You don’t need that TIn in the first place:

public interface Foo<T> {
  void encode(T value);
  T decode;
}

class Example {
  void test() {
    Foo<HashMap<String, Integer>> foo = null;
    foo.encode(new HashMap<String, Integer>());
  }
}

This compiles just fine. In general if you declare a new typevar that is used in only 1 place, it’s pointless – typevars are solely a thing javac worries about, the runtime doesn’t know what generics (typevars) are. Hence, it doesn’t make much sense to use them unless they serve to link 2 different places where a type is mentioned, e.g. ‘the type of parameter to the encode method, the return type of the decode() method? I don’t care what it is, but, for any given usage of the Foo type, it’s the same – that kind of ‘linking’).

Given that there’s no need to introduce an additional type param on the encode method, there’s no need to try to declare a new type var there.

The usual alternative to a typevar that is used in just a single location is ?. There is no functional difference between <F> void foo(List<F> in) and void foo(List<?> in).

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement