amano
amano

Reputation: 11

How to use java.lang.Number polymorphically

I'm trying to use java.lang.Number polymorphically: I have a List where I put multiple Double, Integer, etc. instances, and then I want to polymorphically do arithmetic operations on them (for example double every Number).

We don't have the auto-boxing ability with java.lang.Number and I'm not figuring out a better way to do this without the - not so polymorphic - method multiply(Number n, int factor) in the sample source code that follows... and with this implementation we would need a method for each arithmetic operation (add, subtract, etc.)


EDIT - ENHANCE QUESTION: if we think on the java.lang.Number from a abstraction perspective, we would think that any Number can be part of arithmetic operations but yet again it doesn't seem to exist a simple way to add/subtract/multiply/etc x to a list of Number, independently of their type (Integer, Double, Short...)


Any better ideias? Thanks in advance ;)

Sample source code:

public class NumberTest {

    private List<Number> list = new ArrayList<Number>();    

    public static void main(String args[]) {
        new NumberTest().start();

    }

    protected void start() {
        this.fillList();
        Number num;
        for (int i = 0; i < list.size(); i++) {
            num = this.multiply(list.get(i), 2);
            list.set(i, num);
        }

        System.out.println(this.toString());
    }

    private void fillList() {
        list.add(new Byte((byte) 12));
        list.add(new Short((short) 20));
        list.add(new Integer(30));
        list.add(new Long(40));
        list.add(new Float(50.123));
        list.add(new Double(60.123));
    }

    private Number multiply(Number n, int factor) {
        if (n instanceof Byte) {
            n = n.byteValue() * factor;
        } else if (n instanceof Short) {
            n = n.shortValue() * factor;
        } else if (n instanceof Integer) {
            n = n.intValue() * factor;
        } else if (n instanceof Long) {
            n = n.longValue() * factor;
        } else if (n instanceof Float) {
            n = n.floatValue() * factor;
        } else if (n instanceof Double) {
            n = n.doubleValue() * factor;
        }
        return n;
    }

    @Override
    public String toString() {
        String result = "";
        for (Number num : list) {
            result += num+"\n";
        }
        return result;
    }

Upvotes: 1

Views: 1195

Answers (3)

user949300
user949300

Reputation: 15729

I really don't see why you can't use Number.doubleValue() and do the math. What am I missing?

e.g.

public Double multiply(Number n, double factor) {
   return new Double(n.getDoubleValue() * factor);
}

EDIT ADDED:

@amano has clarified that he wants to change the Objects in the existing List, while maintaining their original type. I guess my first question is, "why"? His example uses a Byte. Multiplying a Byte times most anything will often result in an overflow. Adding a double to an Integer will lose precision. Subtracting an integer from a Byte and forcing the result back into a Byte will usually give a wrong result. Dividing an Integer by an integer will usually lose precision (e.g. 3/2 = 1, not 1.5). Unless you need absolute perfect precision (say, for money) the most mathematically correct solution is to always convert to a double and keep the result as a double. Yes, there will be minor rounding errors but nothing like 3/2 = 1, or (byte)23 - 665544 = who knows what as a byte?

And why would you care that the value was originally a Byte? When you make a big deal about wanting to treat it as a Number? Numbers in, Numbers (technically, Doubles) out.

So I understand better but I'm still missing something. The constraint that the values remain of the same original type causes inaccuracies, plus a lot more work. If you insist on that constraint, yes, you will have to do a lot of instanceof.

Upvotes: 1

Tassos Bassoukos
Tassos Bassoukos

Reputation: 16142

Mirror the Number class hierarchy: write your own NumberWrapper class and for each primitive write a specialized class that knows the actual type and can perform the proper operations.

Late night edit: of course, you could always just use Number#doubleValue() and do your processing only with doubles...

Upvotes: 0

Keith Ripley
Keith Ripley

Reputation: 1068

I agree with Tassos, except that writing all of that sounds quite tedious...

Instead of reinventing the wheel, you might try using something like this: http://code.google.com/p/generic-java-math/. I've never used this library myself but it looks like what you need.

Upvotes: 0

Related Questions