I'm wondering what are the options to specialize generic types in Java, i.e. in a templated class to have specific overrides for certain types.
In my case I was a generic class (of type T) to return null usually, but return "" (the empty string), when T is the String type, or 0 (zero) when its the Integer type, etc.
Merely providing a type-specific overload of a method produces a "method is ambiguous" error:
e.g.:
public class Hacking { public static void main(String[] args) { Bar<Integer> barInt = new Bar<Integer>(); Bar<String> barString = new Bar<String>(); // OK, returns null System.out.println(barInt.get(new Integer(4))); // ERROR: The method get(String) is ambiguous for the type Bar<String> System.out.println(barString.get(new String("foo"))); } public static class Bar<T> { public T get(T x) { return null; } public String get(String x) { return ""; } } }
Is the only option to subclass the generic class with a specific type (see StringBar in the following example?
public static void main(String[] args) { Bar<Integer> barInt = new Bar<Integer>(); StringBar barString2 = new StringBar(); // OK, returns null System.out.println(barInt.get()); // OK, returns "" System.out.println(barString2.get()); } public static class Bar<T> { public T get() { return null; } } public static class StringBar extends Bar<String> { public String get() { return ""; } } }
Is this is the only way, it's a bit of a pain to have to create a subclass for every type I want to specialize instead of an overload of get() in the Bar class.
I'm guessing I could check the instanceof in the Bar.get() method, e.g. T get(T t) { if (t instanceof String) return ""; if (t instanceof Integer) return 0; else return null; }
However I've been taught to avoid instanceof and use polymorphism when possible.
Generics are generic until the types are substituted for them at runtime. Templates are specialized at compile time so they are not still parameterized types at runtime. The common language runtime specifically supports generics in MSIL.
Generics in Java are similar to templates in C++. For example, classes like HashSet, ArrayList, HashMap, etc., use generics very well. There are some fundamental differences between the two approaches to generic types.
A C++ template gets reproduced and re-compiled entirely whenever a template is instantiated with a new class. The main difference is that Java generics are encapsulated. The errors are flagged when they occur and not later when the corresponding classes are used/instantiated.
The actual type arguments of a generic type are. reference types, wildcards, or. parameterized types (i.e. instantiations of other generic 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 ""; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With