I would like to write a method which takes a generic Number as an argument and returns another Number, whose type may possibly differ from the first and is passed as a second argument. Something like this:
public <N1 extends Number, N2 extends Number> N2 op(N1 num, Class<N2> retType) {
//Sample operation, where type conflicts arise.
return retType.cast(num + 3);
}
Of course, I can't just cast N1 to N2 if they are, say, Integer and Long. However, Number offers doubleValue(), intValue(), ... , methods that could allow me to partially work around the issue with a switch/case statement. That would restrict me to the return types of the xxxValue() methods the Number class exposes, thus cutting off AtomicInteger, AtomicLong, BigInteger and BigDecimal.
This is still acceptable for the application I have in mind, but my methods would not be able to properly handle any custom or future official extensions of the Number class if not with a default statement in the switch/case block which should arbitrarily decide which xxxValue() method to invoke, or throw an exception (which I would like to avoid). I could use an enumeration to encapsulate parameters by type, but I am afraid my code would get too convoluted and tricky to use.
The answer to this question gives further insight as to declaring a single generic type for two parameters (it doesn't enforce that both parameters will be, in fact, of the same type at runtime), which sure is worth mentioning here.
What I want to achieve is:
- Declare a method with some generic (in a broad sense)
Numberparameters, possibly more methods with a different number of parameters (e.g. a method with two, a method with three parameters) but still generic in each of them. - The parameters must be restricted to some well-known extensions of
Number(e.g.Integer,Double). - The parameters may come in multiple combinations, potentially any of
(Double, Integer),(Double, Double),(Integer, Double),(Integer, Integer).
I would like not to define multiple methods with different signatures. Even while fixing the return type e.g. to Double, the number of methods would explode as more arguments and types are added.
Of course, I may always resort to specific, ad-hoc implementations for each method, as I am probably not going to need every possible combination of types. I would still like my design to be flexible enough while enforcing these type constraints.