1

Is there any way to make a generic method work with its type parameter as if it were a number? For example, consider a method that takes any number and returns its value doubled while keeping the input type.

static <T> T foo(T number)  {
    return number*2;
}

This doesn't compile because * isn't defined for T and int. Changing T to <T extends Number> doesn't help, casting (T)2 doesn't compile either.

k5f
  • 163
  • 7

3 Answers3

2

Generics only work on objects. You can use the Integer, Double and such classes, but you can't use generics with primatives.

Anubian Noob
  • 13,426
  • 6
  • 53
  • 75
  • Thanks, I forgot that. But it's still possible to multiply an Integer by 2 and assign the result to Integer variable, right? – k5f Nov 25 '14 at 20:48
2

My answer is based on How to add two java.lang.Numbers?

You could convert the values into a known number type and convert it back after the calculation, but this could cause (repeatable) rounding errors.

static <T> T foo(T anyNumber)  {
    BigDecimal result = new BigDecimal(anyNumber.doubleValue()).multiply(new BigDecimal(2));
    if (result instanceof Byte) {
        return (Byte) c.byteValueExtract();
    } else if (result instanceof Double) {
        return (Double) c.doubleValue();
    } else if (result instanceof Float) {
        return (Float) c.floatValue();
    } else if (result instanceof Integer) {
        return (Integer) c.intValue();
    } else if (result instanceof Long) {
        return (Long) c.longValue();
    } else if (result instanceof Short) {
        return (Short) c.shortValueExtract();
    } else if (result instanceof BigDecimal) {
        return result;
    } else {
        throw new NotImplementedException();
    }
}
Community
  • 1
  • 1
Christian Strempfer
  • 7,291
  • 6
  • 50
  • 75
  • What are a and b on the second line? Also, the problem remains - I cant return Byte when the return type is T. – k5f Nov 25 '14 at 21:01
  • @user1859055: Sorry, I messed up the variables. It's fixed now. – Christian Strempfer Nov 25 '14 at 21:12
  • `BigDecimal` arithmetic doesn't always give the same result as arithmetic with `Double` and `Float`. So this will give different answers for certain operations. Of course, multiplication by 2 isn't such an operation; but I think OP wanted something that will work in general. Also, division can prove problematic with `BigDecimal`. – Dawood ibn Kareem Nov 25 '14 at 23:38
  • @DavidWallace: Yes, I mentioned the rounding error, what other problems could occur? – Christian Strempfer Nov 26 '14 at 06:21
  • Basically, whenever you do a `BigDecimal` division, you need to specify how you want the rounding to work - how many decimal places, and which direction. If you don't do that, you'll get an `ArithmeticException` almost all of the time. So if OP's method involves division, there needs to be some special treatment that goes beyond what you've done here. Also, by calling `doubleValue()` on the first line of your method, you can lose a lot of precision if your arguments are `long`. – Dawood ibn Kareem Nov 26 '14 at 08:38
0

There is no way to do operator overloading, eg:

T number = new T();
number * 5;

in Java. I don't know why, but you just can't. Instead, try doing;

static <T> T foo(T number)  {
    return new T(number.getInt()*2);
}

or something to that effect. Hope it helps. "+" operator for Java-classes

EDIT: To expand on what was mentioned in the comments about using Integer i = 5;, this is a feature of Java called autoboxing/unboxing. When you do:

Integer i = 5;
i = i * 4;
int n = i;

Java is really doing:

Integer i = new Integer(5);
i = new Integer(i.intValue() * 4);
int n = i.intValue();
Community
  • 1
  • 1
Kaia
  • 862
  • 5
  • 21