Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Проблема с дженериками в java

#java


Пытаюсь сделать так, чтобы выполнялось арифметическое действие, и, в зависимости
от того, какое число должно выводиться на экран, метод возвращал или int или double.

реализую это так:

@FunctionalInterface
public interface JoinMathAction
{
    T mathAction(Number a, Number b);
}


public class GoMath
{
    public  T getResultMath(T arg1, T arg2, String op)
    {
        Number res = 0;

        if (arg1 instanceof Integer && arg2 instanceof Integer) {
            JoinMathAction mm = (a, b) ->
            {
                int argFirst = a.intValue(), argSec = b.intValue();
                switch (op) {
                    case "/": {
                        if(argFirst == 0 || argSec == 0)
                        {
                            try
                            {
                                throw new DivZeroException("Ділення на 0 неможливе");
                            }
                            catch (DivZeroException d)
                            {
                                System.out.println(d.getMessage());
                            }
                        }
                        else
                        {
                            return argFirst / argSec;
                        }
                    }
                    case "*": {
                        return argFirst * argSec;

                    }
                    case "-": {
                        return argFirst - argSec;
                    }
                    case "+": {
                        return argFirst + argSec;
                    }
                }
                return 0;
            };

            res = mm.mathAction(arg1, arg2);

        } else if (arg1 instanceof Double || arg2 instanceof Double) {
            JoinMathAction mm = (a, b) ->
            {
                double argFirst = a.doubleValue(), argSec = b.doubleValue();
                double result = 0;

                switch (op) {
                    case "/": {
                        if(argFirst == 0 || argSec == 0)
                        {
                            try
                            {
                                throw new DivZeroException("Ділення на 0 неможливе");
                            }
                            catch (DivZeroException d)
                            {
                                System.out.println(d.getMessage());
                            }
                        }
                        else
                        {
                            return argFirst / argSec;
                        }
                    }
                    case "*": {
                        return argFirst * argSec;
                    }
                    case "-": {
                        return argFirst - argSec;
                    }
                    case "+": {
                        return argFirst + argSec;
                    }
                }
                return result;
            };

            res = mm.mathAction(arg1, arg2);
        }
        return (T) res;
    }
}


Все работает, но как сделать с двух switch один? И как это сделать грамотно?
    


Ответы

Ответ 1



Что не так с генериками уже объяснили. Я же представлю вариант выхода из безвыходной ситуации с одним switch-ом. Сделайте из Number BigDecimal. У него есть методы, реализующие арифметические операции. Складывайте, вычитайте, умножайте и делите BigDecimal в одном switch-е, а результат переведите обратно в int или double: public T getResultMath(T arg1, T arg2, String op) { BigDecimal bigArg1 = new BigDecimal(arg1 instanceof Integer ? arg1.intValue() : arg1.doubleValue()); // или в любом случае используя doubleValue BigDecimal bigArg2 = new BigDecimal(arg2.doubleValue()); BigDecimal bigResult; switch (op) { ... case "*" : bigResult = bigArg1.multiply(bigArg2); break; ... } // Округления при переводе в int сами найдёте как сделать return (T) (arg1 instanceof Integer ? new Integer(bigResult.intValue()) : new Double(bigResult.doubleValue())); } Вообще-то не обязательно использовать BigDecimal. Можно тот же double с успехом применить.

Ответ 2



Вообще это проблема не про Generic, а про autoboxing. У классов Integer и Double тоже не определено ни одной арифметической операции и если вы попробуете скомпилировать код вида: void add(Integer b, Integer c){ Integer a = b + c; } В Java 1.4, то у вас ничего не получится, такой код начинает работать только с версии 1.5, когда собственно и появился autoboxing. И в Java 1.5 в байт коде будет: void add(Integer b, Integer c) { Integer a = Integer.valueOf(b.intValue() + c.intValue()); } А т.к. для класса Number нельзя заранее определить как его преобразовать, то и арифметическую операцию применить нельзя.

Комментариев нет:

Отправить комментарий