2

I have been trying to write a simple but flexible class that holds some values of generic type T. T extends Number, which means I just want this class to deal with everything from bytes to longs. I am not all that familiar with how to use generics, so my main question to you guys is if there's a way to shorten the following set of functions into one function in order to reduce the unnecessary code duplication. The following is the given code:

    public static byte distanceSq(byte x1, byte y1, byte x2, byte y2) {
        x1 -= x2;
        y1 -= y2;
        return (byte) (x1 * x1 + y1 * y1);
    }
    
    public static short distanceSq(short x1, short y1, short x2, short y2) {
        x1 -= x2;
        y1 -= y2;
        return (short) (x1 * x1 + y1 * y1);
    }
    
    public static int distanceSq(int x1, int y1, int x2, int y2) {
        x1 -= x2;
        y1 -= y2;
        return (int) (x1 * x1 + y1 * y1);
    }
    
    public static float distanceSq(float x1, float y1, float x2, float y2) {
        x1 -= x2;
        y1 -= y2;
        return (float) (x1 * x1 + y1 * y1);
    }
    
    public static double distanceSq(double x1, double y1, double x2, double y2) {
        x1 -= x2;
        y1 -= y2;
        return (double) (x1 * x1 + y1 * y1);
    }
    
    public static long distanceSq(long x1, long y1, long x2, long y2) {
        x1 -= x2;
        y1 -= y2;
        return (long) (x1 * x1 + y1 * y1);
    }

I have tried to write something along the lines of:

    public static <U extends Number> U distanceSq(U x1, U y1, U x2, U y2) {
        x1 -= x2;
        y1 -= y2;
        return (x1 * x1 + y1 * y1);
    }

However, since the variables are objects now, the operators cannot resolve them. I tried to convert them into their appropriate wrapper using an instanceof statement, but that got me nowhere either.

  • [This](https://stackoverflow.com/questions/29010699/can-i-add-two-generic-values-in-java) might help – Gryphon Aug 31 '20 at 05:29
  • Does this answer your question? [How to add two java.lang.Numbers?](https://stackoverflow.com/questions/2721390/how-to-add-two-java-lang-numbers) – Charlie Armstrong Aug 31 '20 at 05:31
  • or [this](https://stackoverflow.com/questions/3873215/can-i-do-arithmetic-operations-on-the-number-baseclass) – Vladislav Varslavans Aug 31 '20 at 05:31
  • As the linked questions and answers show, this is not possible in Java. This is also why there are so many explicit method overloads in [java.lang.Math](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Math.html), which are also explicitly implemented in terms of their separate types in [this OpenJdk implementation](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/Math.java) – Hulk Aug 31 '20 at 05:38
  • 1
    Does this answer your question? [Can I do arithmetic operations on the Number baseclass?](https://stackoverflow.com/questions/3873215/can-i-do-arithmetic-operations-on-the-number-baseclass) – Hulk Aug 31 '20 at 05:41
  • I have tried doing something similar to a lot of these suggestions. Such as having an if statement to check what type U is and then running a different operation using .intValue() or .doubleValue() to get the result. But that just makes it much too complicated compared to C++ templates so I avoided it. – antshekhter Aug 31 '20 at 20:44

1 Answers1

0

You can define your method like this

public static  <T extends Number> Number distanceSq(T x1,T y1,T x2,T y2){
    double x = x1.doubleValue() - x2.doubleValue();
    double y = y1.doubleValue() - y2.doubleValue();
    return (x * x + y * y);
}

And it can be called as

Integer r1 = distanceSq(a1, b1, a2, b2).intValue();
Byte r2 = distanceSq(x1, y1, x2, y2).byteValue();
Silhoutte
  • 57
  • 10
  • Thanks for the help, but it seems like it will cause longs to be truncated or rounded off. From what I can tell, java doesn't have anything as convenient as C++ templates. I'll have to just duplicate code in different types to avoid instantiating primitive wrappers. – antshekhter Aug 31 '20 at 20:41