-1

I am trying to learn generics and came across this question. I am very confused why the code is not working

public class Test {
    public static void main(String args[]) {
        int result;

        result = printValues(new Pair<String, Double>("Pair1", 3.0), new 
        Pair<String, Double>("Pair2", 4.0));
        System.out.println(result);
    }

    public static <K, V extends Integer> int printValues(Pair<K, V> p1, Pair<K, V> p2) {
        return p1.getValue() + p2.getValue();
    }

    class Pair<K, V> {
        private K key;
        private V value;

        public Pair(K key, V value) {

            this.key = key;
            this.value = value;
        }

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public void setValue(V value) {
            this.value = value;
        }

    }
}

I am getting following compliation error: The method printValues(Test.Pair, Test.Pair) in the type Test is not applicable for the arguments (Test.Pair, Test.Pair) I tried to change the method printValues as follow:

public static <K, V extends Number> int printValues(Pair<K, V> p1, Pair<K, V> p2) {
    return p1.getValue() + p2.getValue();
}

But then the error is "The operator + is undefined for the argument type(s) V, V"

Edit:

      public static <K, V extends Number> int printValues(Pair<K, V> p1, 
        Pair<K, V> p2) {
           return p1.getValue().intValue() + p2.getValue().intValue();
         }

Now i get error on printValues(new Pair

No enclosing instance of type Test is accessible. Must qualify the allocation with an enclosing instance of type Test (e.g. x.new A() where x is an instance of Test).

Jeena
  • 309
  • 1
  • 5
  • 14
  • `V`, though being a subclass of `Number`, is still a class. You can't use `+` on classes, only on primitives (and `String`s). An `Integer` (wrapper class) is not the same as an `int` (primitive). You can use the methods of the `Number` class: [documentation](https://docs.oracle.com/javase/10/docs/api/java/lang/Number.html). – Zabuzard Aug 07 '18 at 09:07
  • 1
    Possible duplicate of [How to add two java.lang.Numbers?](https://stackoverflow.com/questions/2721390/how-to-add-two-java-lang-numbers) – Zabuzard Aug 07 '18 at 09:08
  • I wonder why eclipse is giving me a more complete error message: "The method printValues(Test.Pair, Test.Pair) in the type Test is not applicable for the arguments (Test.Pair, Test.Pair)" ??? – user85421 Aug 07 '18 at 09:16
  • Its not problem of Numbers, So plzz not mark it as duplicate, – Jeena Aug 07 '18 at 09:18
  • `Double` does not extends `Integer` ^^ – azro Aug 07 '18 at 09:19
  • 1
    but it was problem of `Number` before the question changed... – user85421 Aug 07 '18 at 09:21
  • @Jeena The proposed solution in your accepted answer (`1.`) is exactly whats written in the linked duplicate. So the duplicate indeed solved your issue. – Zabuzard Aug 07 '18 at 09:30

2 Answers2

3

There are few problems with your code

  1. new Pair<String, Double> is not applicable to <K, V extends Integer> as Double doesn't extend Integer. One way to do it is to redefine the method with Number as per this answer to account for different implementations of Number:

    public static <K, V extends Number> Number printValues(Pair<K, V> p1, Pair<K, V> p2) {
      if(p1.getValue() instanceof Double || p2.getValue() instanceof Double) {
        return new Double(p1.getValue().doubleValue() + p2.getValue().doubleValue());
      } else if(p1.getValue() instanceof Float || p2.getValue() instanceof Float) {
        return new Float(p1.getValue().floatValue() + p2.getValue().floatValue());
      } else if(p1.getValue() instanceof Long || p2.getValue() instanceof Long) {
        return new Long(p1.getValue().longValue() + p2.getValue().longValue());
      } else {
        return new Integer(p1.getValue().intValue() + p2.getValue().intValue());
      }
    }
    
  2. The Pair class should be declared static so you can use it in static main() method:

    static class Pair<K, V> {
    
  3. No need to declare the generic types on objects, starting from Java 7 it's enough to use the <> operator:

    Number result = printValues(new Pair<>("Pair1", 3.0), new Pair<>("Pair2", 4.0));
    
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
0
public static <K, V extends Number> int printValues(Pair<K, V> p1, Pair<K, V> p2) {
    return p1.getValue().intValue() + p2.getValue().intValue();
}

In Java you cannot inherit the + operator (or any other operator) if you subclass Number. On the other hand, methods are inherited (i.e. intValue)

memo
  • 1,868
  • 11
  • 19
  • The problem with the answer is that it is not precise enough. The terminology is off. `+` does not work on classes (except `String`). It doesn't even work on `Integer` as this is a class and not a primitive. This has nothing to do with inheritance. And methods like `intValue` are declared in the parent class `Number`. However, using `intValue` if the passed `Number` is a `Double` yields a wrong result for the addition. The only way of doing it correct is to check the type and use the appropriate conversation method. Then use `+` on primitives. – Zabuzard Aug 07 '18 at 09:27
  • @Zabuza I agree with your points. The `+` operator applies to primitive types in Java (and String) and the fact that you can use it on instances of Integer, Double etc. is because of the automatic unboxing. My point was that it does not apply to subclasses of Integer etc. As for intValue, well, his method has an `int` return type. Of course, he can use `doubleValue()` instead. – memo Aug 07 '18 at 09:31