3

I have read several pages on generic methods and have some sort of grasp on them, but I still don't understand them. So say I have a method to multiply two numbers and return the product:

public double multiply(SomeNumberVariableType x, SomeNumberVariableType y){
    return x * y;
}

How can I use bounded generics to have only a number type permitted as parameters?

2
  • 2
    The type of each of the operands of a multiplicative operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs. Commented Dec 28, 2013 at 22:01
  • What number types do you want to use as parameters? I don't think you can use bounded generics per se, but this looks like a problem that can be solved using polymorphism. Commented Dec 28, 2013 at 22:01

4 Answers 4

4

Maybe this is your intention:

public static <N extends Number> double multiply(N x, N y){
    return x.doubleValue() * y.doubleValue();
}

Although I must also say that the generic use of Number instead of concrete immutable value types like java primitive double is probably not so healthy because in the example above the arguments could even be of different types, for example Integer and Double.

Attention:

I confirm, the arguments can be of different types as given signature above. So the answer of Bohemian is wrong. I have tested it just now (but knew it already before). The compiler only guarantees that both arguments are of type Number, nothing else.

In order to assert the same argument types the compiler needs self-referencing generics. This feature is not fulfilled by Number-class (that is <N extends Number<N>> is unfortunately not possible). That is why I consider the whole Number approach as not really healthy. Here a test code which everyone can execute:

Integer x = Integer.valueOf(10);
Double y = new Double(2.5);
System.out.println(multiply(x, y));
// Output: 25.0
Sign up to request clarification or add additional context in comments.

Comments

2

In general, Java generics are not appropriate for math.

In Java:

  • Generics are object only.
  • There are no mathematical operators for objects.

It looks like you can perform math on objects because you can do something like this:

Integer a = 1;
Integer b = 2;
Integer c = a + b;

But that is only due to autoboxing. What actually happens is the compiler replaces that code with this:

Integer a = new Integer(1);
Integer b = new Integer(3);
Integer c = Integer.valueOf(a.intValue() + b.intValue());

With generics you can specify a bound so that your type must be Number or a subtype of it:

static <N extends Number> N multiply(N n1, N n2) {
    return n1 * n2; // but you cannot do this because the type is not known
                    // so the compiler cannot do autoboxing
}

If a supertype is known, you can call methods on them so you can do this as has been pointed out:

static <N extends Number> double multiply(N n1, N n2) {
    return n1.doubleValue() * n2.doubleValue();
}

But that is no different than the following:

static double multiply(double n1, double n2) {
    return n1 * n2;
}

Except that the generic version can, for example, take BigDecimal as an argument which will of course not provide a reliable result (see BigDecimal#doubleValue). (Neither will Long for that matter.)

If you were really determined you could program your own number classes and use polymorphism. Otherwise use overloads or (best of all) stick to one type.

1 Comment

My upvote for the statement that generics are object-related only.
1

You can specify a bound to your type by coding <T extends Number>:

public static double <T extends Number> multiply(T x, T y){
    return x.doubleValue() * y.doubleValue();
}

Which restricts the Number types to being the same type, eg an Integer and an Integer, but not an Integer and a Long.

but you don't need generics at all:

public static double multiply(Number x, Number y){
    return x.doubleValue() * y.doubleValue();
}

Which allows any two Numbers, eg an Integer and a Long.

3 Comments

When the method is called the I want to be an to use an int variable or a double variable in the parameters. This only lets me use a number object
@Dando18 Java generics are object only.
Please consider my additional remark about equality of argument types in my edited answer.
0

what abt this

import java.util.function.BinaryOperator;
public class GenericArithmetic {

    public static <T extends Number> BinaryOperator<T> get_multiplier(T t1){
        BinaryOperator<Integer> intMultiper = (i1, i2) -> i1 * i2;
        BinaryOperator<Float> floatMultiper = (i1, i2) -> i1 * i2;

        // should cache
        switch (t1.getClass().getName()) {
            case "java.lang.Integer":
                return (BinaryOperator<T>) intMultiper;
            case "java.lang.Float":
                return (BinaryOperator<T>) floatMultiper;
            default:
                return null;
        }
    }

    public static <T extends Number> Number multiply(T x, T y) throws Exception{
        var multiplier = get_multiplier(x);
        var res = multiplier.apply(x, y);
        return res;
    }


    public static void main(String[] args) throws Exception{
        var a1 = 3;
        var a2 = 5;

        var res = multiply(a1, a2);
        System.out.println(res);

        var b1 = 2.0f;
        var b2 = 3.0f;
        var res2 = multiply(b1,b2);
        System.out.println(res2);   
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.