Передача унифицированных параметров и безопасность типов с Java генериками - PullRequest
0 голосов
/ 29 февраля 2020

Поскольку мне часто приходится иметь дело с рандомизацией, я хотел бы создать класс, который удобно группирует все те функции, которые мне обычно нужны. Среди прочего я подумал о обобщенной функции c fromPool(), которая, учитывая переменное число объектов, случайным образом возвращает один из них. Конечно, мне пришлось комбинировать varargs и generics, которые я только что обнаружил, может быть большим табу в зависимости от случаев (и я подозреваю, что один из них). Вот код:

abstract public class RandomGenerator {

    public static int fromRange(int min, int max) {

        return (int) (Math.random() * (max + 1 - min)) + min;
    }

    public static <T> T fromPool(T ... pool) {

        return pool[fromRange(0, pool.length - 1)];
    }
}

Проблема в том, что я, конечно, могу передавать fromPool() объекты разных типов, что делает тип возвращаемого значения чрезвычайно переменным. Так, например, я могу сделать что-то вроде этого:

int n = (int) RandomGenerator.fromPool("String", 6);

, который будет работать до тех пор, пока fromPool() не вернет "String", а затем вызовет это исключение.

Исключение в потоке "main" java .lang.ClassCastException: класс java .lang.String не может быть приведен к классу java .lang.Integer (java .lang.String и java. lang.Integer находится в модуле java .base загрузчика 'bootstrap') в Test.main (Test. java: 109)

Вот что мне было интересно:

1) К этому относится предупреждение «Безопасность типов: потенциальное загрязнение кучи через пул параметров varargs», которое появляется при объединении обобщенных и varargs? Есть ли что-то еще к этому?

2) Нет ли способа ограничить эффект обобщений, чтобы вы не могли передавать объекты, которые никоим образом не совместимы друг с другом, к одному и тому же вызову функции ? По сути, это какой-то автомат c, трансверсальная перегрузка (я чувствую, что я прошу луну)?

3) На самом деле ранее я написал гораздо менее обобщенную c версию fromPool(), которая имеет дело только с объектами Number.

public static <N extends Number> N fromPool(N ... pool) {

    return pool[fromRange(0, pool.length - 1)];
}

Вопреки тому, что я изначально считал, эта версия также небезопасна, поскольку приведение между примитивными типами не создает никаких проблем, приведение между различными классами-обертками не возможно, поэтому вызывает еще раз ClassCastExceptions. Разве нет способа настроить эту версию, чтобы сделать хотя бы эту версию безопасной?

Большое спасибо за понимание:)

1 Ответ

1 голос
/ 29 февраля 2020

Вы можете попробовать что-то похожее на приведенное ниже.

RandomGenerator.<String>fromPool("String", "Something");

Таким образом, вы будете явно указывать тип объекта generi c для вызова этой функции. А также вам не нужно приводить возвращаемое значение, поскольку тип generi c явно объявлен.

Если вы не укажете тип объекта generi c, он будет выведен как java.lang.Object.

...