Changing the value in the Generics object in Java

I recently started to learn about generics in Java, and I understand the basic concepts of generics. However, one thing I don't understand is that I don't know why the following method doesn't work:

public class Generics<T extends Number> {
    T num;

    Generics(T n){
        num = n;
    }

    //...

    T timesTwo() {                 //Return the value that's twice as much as 'num'
        return num * 2;
    }
}

It was my first approach, and I kind of understand why it is not working. The error message said: The operator * is undefined for the argument types(s) T, int.

I guess Java couldn't multiply the T and int type together. (But shouldn't the compiler be able to auto-unbox T since it's involved in an expression AND the class extends Number?)

So I gave up on this method and tried to replace it with this method:

T times(T i) {   //This method was supposed to receive another T object as 
                 //an argument and multiply them together, then return the output
    return num * i;
}

But once again, the exact same error message appeared (the only change was that int was replaced by T).

Why is the code not working, and how can I fix it?

1 answer

  • answered 2021-04-08 15:20 Atmas

    I agree with the first two comments. Also, it's not a generics problem, it's just that the method doesn't work because it's not supposed to work because the boxing assumption you concluded doesn't apply here.

    Autoboxing and Unboxing are supplied for some of the Number types but not all. See table below: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

    So while this works the way you expect (because both types are in the supported table):

    public static void main(String[] args) {
        Integer a = 3;
        Integer b = 2;
        Number answer = a * b;
        System.out.println("Answer: " + answer);
    }
    

    This intuitively equivalent code will NOT work:

    public static void main(String[] args) {
        Number a = 3;
        Number b = 2;
        Number answer = a * b;
        System.out.println("Answer: " + answer);
    }
    

    In fact, from the Compiler's perspective, it gives you the same cross-eyed look you would get if you tried this:

    public static void main(String[] args) {
        String a = "what does it even mean to multiply a string with a number..??";
        Byte b = 2;
        Number answer = a * b;
        System.out.println("Answer: " + answer);
    }
    

    So to finish the point, from the compiler's perspective, since auto-boxing does not apply, it's just as confused as to how to multiply two Numbers as it is how to multiply two other random objects like a String and a Byte and reports the error accordingly