Image

Categories:

Передача параметров по ссылке - вопрос по стилю

Один из стандартных упреков в адрес Java со стороны новичков - отсутствие параметров, передаваемых по ссылке (как "&arg" в C++ или "var arg" в Паскале). На самом деле упрек столь же несостоятелен, как и отсутствие goto - по крайней мере, в 99.99% случаев. Действительно, грамотно спроектированный объектно-ориентированный код попросту не нуждается в таких параметрах (что подтверждается огромным количеством довольно качественных библиотек от Sun, которые прекрасно обходятся без передачи по ссылке). Хороший метод либо модифицирует состояние объекта (может быть, своего аргумента), либо возвращает всю информацию в новом объекте.

Все это так, но меня не оставляет мысль, что существует те самые 0.01% случаев, когда передача параметра по ссылке все же оправдана. (Ведь и goto очень-очень редко все-таки применялся в высокопрофессиональных библиотеках на C++ и Паскале.) В данный момент я, как мне кажется, столкнулся как раз с таким случаем, и мне интересно, какой вариант решения посоветуют уважаемые коллеги с этого форума. Задаю вопрос отчасти потому, что с моим коллегой по работе наши мнения разошлись радикально :)

Итак. У меня есть метод
public static DoubleRange rangeOf(PArray array)
Здесь PArray - некий класс, описывающий массив чисел, а DoubleRange - пара чисел min и max (аналог апачевского DoubleRange). Метод одновременно вычисляет минимум и максимум в массиве, которые и возвращает в виде экземпляра DoubleRange.

Я хочу иметь перегруженную версию этого метода, которая, кроме диапазона min..max, вернет также индексы в массиве найденных минимума и максимума. Просто на всякий случай: подобная информация нужна редко. Это еще 2 целых числа, в моем случае long (мои массивы имеют 64-битовую индексацию). В Паскале можно было бы указать их в качестве дополнительных var-параметров. Что делать в Java?

Варианты следующие.

1) Создаем новый класс DoubleRangeAndIndexes, содержащий min, max, indexOfMin, indexOfMax, и возвращаем его экземпляр. Крайне уродливо: такой класс, в отличие от DoubleRange, не описывает никакой осмысленной сущности. Получается "класс ради метода", хотя на самом деле все должно быть наоборот - методы ради обслуживания классов.

2) Передаем оставшиеся 2 числа каким-нибудь кривым, но поддерживаемым в языке способом. Самый очевидный - массив:
public static DoubleRange rangeOf(PArray array, long[] minAndMaxIndexes)
Метод записывает индексы минимума и максимума в ячейки minAndMaxIndexes[0] и minAndMaxIndexes[1]. До чего же мерзко, однако. Особенно последующее использование: в коде появляются "магические номера" 0 и 1.

3) Используем org.omg.CORBA.LongHolder:
public static DoubleRange rangeOf(PArray array, LongHolder indexOfMin, LongHolder indexOfMax)
Собственно, это единственный способ передать примитивное значение по ссылке в Java при помощи стандартного API. Более того, само происхождение пакета намекает на передачу параметров по ссылке - очевидно, эти Holder-ы появились в CORBA для взаимодействия с языками, поддерживающими такую возможность. В данный момент у меня так и сделано. Мой коллега, однако, грязно ругается: какое, мол, отношение имеет CORBA к моей алгоритмической библиотеке, тем более к подсчету минимумов и максимумов. А я говорю: зато этот пакет включен в стандартную поставку JRE.

4) Пишем и используем свой эквивалент LongHolder, например, в виде вложенного класса, специально для этого метода. Не так плохо, как вариант #1, но все равно "класс ради метода". К тому же у пользователей возникает очевидный вопрос: зачем написан класс, стопроцентно эквивалентный уже имеющемуся в стандартных библиотеках?

5) Пишем свой класс MinAndMaxPosition, позволяющий хранить (и модифицировать) 2 целых числа с названиями min и max. Передаем вместо пары LongHolder-ов. Но разве такой класс - осмысленная сущность?

Хотелось бы послушать, какой вариант предпочли бы уважаемые коллеги. Или, может быть, существует совершенно иное решение?

На всякий случай, если кому-то интересно, вот обсуждение этого же вопроса на другом форуме: http://xpoint.ru/forums/thread/40881.xhtml