Java generics (template) specialization possible (overriding template types with specific types)

All things considered, the concensus appears to be that the StringBar method mentioned in the question is the only way to go.

  public static class StringBar extends Bar<String> {
    public String get() {
      return "";
    }
  }

Generics in Java are very different from templates in C++ in this respect. It is not possible to write a specific version of a generic class to do something different for a particular case, as C++ can do. It is also not possible to determine at run time what T is - this is because that information is not passed into the byte code (object code) and so doesn't even exist at runtime. This due to something called "type erasure".

BarString and BarInt would be the obvious way of doing this, but there are improvements you can make. For example you can write a generic Bar to cover the common cases, and then write specialized BarString and BarInt to implement special cases. Ensure that the instances can only be created through a factory, which takes the class of the object to be processed:

class Bar<T> {
  class BarString extends Bar<String> {
    // specialist code goes here
  }


static Bar<T> createBar(Class<T> clazz) {
  if (clazz==String.class) {
    return new BarString();
  } else {
    return new Bar<T>;
}

That probably won't compile, but I don't have the time to work out the exact syntax. It does illustrate the principle.


The compiler is actually correct, because the following code is compile-time checked (Bar<String> barString = new Bar<String>();) when compiled, from

public static class Bar<T> {

    public T get(T x) {
      return null;
    }

    public String get(String x) {
      return "";
    }  
  }

to

public static class Bar<String> {

    public String get(String x) {
      return null;
    }

    public String get(String x) {
      return "";
    }  
  }

and is ambiguous as you can't have 2 identical methods with the same return types and the same parameter arguments.

See an explanation by Jon Skeet's:

  • What is the concept of erasure of generics in java?
  • Java Generics - Types erasures - when and what happens?

You can subclass Bar<T> and create StringBar (note I removed the static keyword) and override get() method.

public class BarString extends Bar<String> {

    @Override
    public String get(String x) {
        return "";
    }
}

Tags:

Java

Generics