Общий алгоритм для длинных и целых чисел

#java

#java

Вопрос:

Моя идея показывает, что у меня есть общий код для двух классов, и я должен сделать его единым из-за СУХОГО правила (не повторяйтесь).

 class LongPersistence {
    public void storeSomeNiceNumber(@NotNull Long l) {
            if (l < 0) {
                throw new RuntimeException("value should not be negative");
            }
            someNicePersistence.store(new String(l).getBytes());
        }
    }

    public Long retrieveSomeNiceNumber() {
        try {
            byte[] bytesRepr someNicePersistence.retrieve();
            Long value = Long.parseLong(new String(bytesRepr));
            return value;
        } catch (SomeNicePersistenceException e) {
            return 0L;
        }
    }
}
 

Итак, я начал работать…

 class Persistence<N extends Number> {
 

… и не удалось, поскольку:

  1. Число нельзя сравнить с 0.
  2. Я не могу вернуть 0 к числу.

Я думаю, что это должно быть возможно на четко определенном языке, поскольку Java я рассматривал до сих пор. Я что-то упускаю? Пожалуйста, посоветуйте, как сделать этот алгоритм общим для Long и Integer (и в качестве задачи A для любого числа)

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

1. Есть некоторые вещи, которые лучше всего выполнять отдельно. Я понимаю, что вы хотите сделать.

2. Если вы уверены, что у вас будут только подклассы Long и Integer, вы можете просто вызвать метод Number longValue() и сравнить его с нулем. Однако, если есть какая-либо вероятность того, что вы добавите подклассы для float , double, BigDecimal или BigInteger , сравнения longValue() будет недостаточно, так как это приведет к неправильным результатам для значений от -1 до 0, таких как -0.5 (или в случае BigInteger, отрицательных чисел, 63-й бит которых равен нулю).

3. @VGR странно, что Java Number не реализует signum(), поскольку это базовая операция процессора для получения знакового бита. Также может быть выполнено нейтральное значение 0. Это я могу сделать, используя функциональный интерфейс для синтаксического анализа и разбирая «0», однако я надеялся, что вы, ребята, каким-то образом обновите интерфейс на Java, о котором я еще не знаю.

4. Примитивные классы-оболочки на самом деле не предназначены для выполнения математики; они в основном предназначены для размещения примитивных значений в контейнерах, для которых требуются объекты, такие как коллекции и карты.

5. @VGR спасибо, что немного почистил мою голову. Мне потребовалось слишком много от java.lang.Number — вместо этого я перенесу математику в другой класс.

Ответ №1:

Благодаря @VGR я понял, что мне требуется математическая логика из класса java.lang.Number, который предназначен для хранения чисел только как объектов (что-то вроде типа Variant), поэтому я перенес математику в другой интерфейс, что, на мой взгляд, имеет больше смысла.

 public interface NumberMath<E extends Number> {
    E parse(String string);
    String toString(E e);
    E zero();
    int signum(E e);
}

class NumberPersistence<E extends Number> {

    private final NumberMath<E> math;
    private final SomeNicePersistence someNicePersistence;

    public NumberPersistence(NumberMath<E> math, SomeNicePersistence persistence) {
        this.someNicePersistence = persistence;
        this.math = math;
    }

    public void storeSomeNiceNumber(E l) {

        if (math.signum(l) < 0) {
            throw new RuntimeException("value should not be negative");
        }
        someNicePersistence.store(math.toString(l).getBytes());

    }

    public E retrieveSomeNiceNumber() {

        try {
            byte[] bytesRepr = someNicePersistence.retrieve();
            E value = math.parse(new String(bytesRepr));
            return value;
        } catch (SomeNicePersistenceException e) {
            return math.zero();
        }
    }
}
 

Я ограничил E числом, но, честно говоря, в данном случае это больше не требуется.