2013-11-29 4 views
5

Как некоторые из вас знают, C++ позволяет сделать это:Можно ли вернуть L-значения из функции

get(array, 5) = 5; 

с функцией get реализованного что-то вроде:

int& get(int* array, int index) { return array[index]; } 

ли что-то подобное возможно в Java? В частности, я хотел бы инкапсулировать логику индексации массива в функцию (высокопроизводительным способом).

+0

Почему бы просто не использовать 'array [index] = 5' без какой-либо функции между ними? Я не понимаю, как вы пытаетесь добиться такого увеличения производительности. – noone

+0

@noone Цель состоит в том, чтобы ** инкапсулировать логику индексирования массива **, а * поддерживать * хорошую производительность. –

+0

@AleksandrDubinsky, если ваша точка заключается в инкапсуляции логики индексирования массива, то одним из способов было бы написать вспомогательный класс с помощью метода типа setValue (int [] array, int customIndex, int newValue). Каждое решение для массива, использующего примитивные типы, будет связано с этим способом. –

ответ

0

Java передает аргументы и возвращаемые значения «по значению», что означает, что C++ - ссылки типа не поддерживаются. По дизайну, нет способа сказать компилятору «не копировать переменную a, вместо этого сделать alias, и пусть другая функция использует ту же ячейку памяти и модифицирует мою переменную, если захочет».

Обходной путь заключается в том, чтобы вместо этого передать ссылку на объект-обертку. Для массивов объект-оболочка сохранит ссылку на массив и смещение. Вот способ, используя встроенные классы:

IntBuffer get(int[] array, int index) 
{ 
    return IntBuffer.wrap(array, index, 1).slice(); 
} 

get(array, 5).put(42); 

И еще (который не работает для примитивных типов):

List<Object> get(Object[] array, int index) 
{ 
    return Arrays.asList(array).subList(offset, offset + 1); 
} 

get(array, 5).set(0, new Object()); 

Это должно быть так же быстро, как прямой доступ к массиву, потому что JIT знает, как оптимизировать весь код котельной.

Но поскольку Java не позволяет вам переопределить оператор =, синтаксис не так хорош, как хотелось бы.

2

Нет такого варианта. Необъекты (литералы) являются примитивными типами, и вы не можете просто подключить две переменные, чтобы при ее изменении один из них также менялся.

Все объекты представлены его ссылками, которые вы можете использовать для изменения некоторых атрибутов удерживаемого объекта. Это означает, что вы можете написать:

getMyObject().setX(newXVal); 

Но вы не можете писать:

getMyObject().getX() = newVal; 

Поскольку метод getX() (и любой метод, который не возвращается тщетным) всегда возвращает значение типа (при возврате Object его это его адрес, при возврате литерала это просто значение этого литерала).

Если вы хотите написать оптимизированный по производительности код в Java - сначала напишите, затем измерьте и затем настройте его (если шаг измерения говорит, что он медленный). У JVM достаточно оптимизаций, чтобы сделать ваш код максимально быстрым, вам не нужно слишком рано оптимизировать код.

+0

Жаль, что звучит неблагодарно, но этот ответ плохо написан и смущен. –

+0

@Александр Дубинский почему путают? Использование функции-как-L-значение означает, что вы должны использовать пользовательские оболочки для примитивных типов. Это довольно антиэффективное решение. –

+0

Вы правы в том, что Integer неизменен, пользовательская оболочка является одним из решений и имеет низкую производительность. Я имею в виду, что текст запутан. Я объясню. «Не-объекты-значения (литералы)» нечувствительны, не в последнюю очередь потому, что «литералы»! = «Ссылочный тип». «Все объекты являются ссылками ... единственным способом доступа к нему ...» также не имеет значения. Для создания обертки не требуется расширение номера. «Я бы не рекомендовал этот вариант, если вы не были уверены, что ваш код слишком медленный», кажется, говорит, что обертки будут * улучшать * производительность. Общий совет о преждевременной оптимизации просто нежелателен. –

1

Это невозможно. Java не передает аргументы метода по ссылке; он передает их по значению.

Вы можете использовать что-то вроде этого:

public static <T> void setArrayValue(T [] array, int index, T set) { 
    ... 
} 
Смежные вопросы