Как я могу имитировать передачу по ссылке в Java?

#java #pass-by-reference

#java #передача по ссылке

Вопрос:

Я полный новичок в Java. Я знаю, что Java обрабатывает все параметры как передачу по значению, и есть несколько других потоков, где люди объясняют это.

Например, в C я могу сделать:

 void makeAThree(int amp;n)
{
   n = 3;
}
int main()
{
   int myInt = 4;
   makeAThree(myInt);
   cout << myInt;
}
  

Который выведет 3. Я знаю, что в Java все параметры передаются по значению, и поэтому вы не можете манипулировать переданным параметром. Существует ли стандартный способ имитации передачи по ссылке в Java? Нет ли способа вызвать функцию, которая управляет переданной переменной? Мне сложно понять, что нет никакого способа сделать это.

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

1. Java использует передачу по значению. почему вы хотите это имитировать? возможно, вы упускаете какой-то момент. можете ли вы уточнить, что вы хотите?

2. В качестве примечания, в Java такой код, вероятно, будет выглядеть так n = makeAThree(n)

Ответ №1:

Основной способ, которым вы можете имитировать передачу ссылки, — это передать контейнер, содержащий значение.

 static void makeAThree(Reference<Integer> ref)
{
   ref.set(3);
}

public static void main(String[] args)
{
  Reference<Integer> myInt = new Reference<>(4);
  makeAThree(myInt);
  System.out.println(myInt.get());
}
  

Поскольку в Java это ссылки на объекты, которые передаются по значению (сам объект вообще никогда не передается), установка ref в 3 in makeAThree изменяет тот же объект, на который ссылается myInt in main() .

Отказ от ответственности: Reference это не тот класс, который вы можете просто использовать с готовой Java. Я использую его здесь в качестве заполнителя для любого другого типа объекта. Вот очень простая реализация:

 public class Reference<T> {
    private T referent;

    public Reference(T initialValue) {
       referent = initialValue;
    }

    public void set(T newVal) {
       referent = newVal;
    }

    public T get() {
       return referent;
    }
}
  

Редактировать

Это не значит, что изменять аргументы вашего метода — отличная практика. Часто это считается побочным эффектом. Обычно рекомендуется ограничить выходные данные вашего метода возвращаемым значением и this (если метод является методом экземпляра). Изменение аргумента — это очень «C» способ разработки метода и плохо соотносится с объектно-ориентированным программированием.

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

1. «Изменение аргумента — это очень»Си» способ разработки метода и плохо соотносится с объектно-ориентированным программированием». Я думаю, что это полностью ортогонально ООП, и во многих случаях это может быть лучшим дизайнерским решением для данной проблемы.

Ответ №2:

Вы можете использовать массив размером 1

Ответ №3:

Java передает все по значению, если это объект, то будет передано ссылочное значение объекта. Это как,

 void someMethod()
{
   int value = 4;
   changeInt(value);
   System.out.printlin(value); 
}

public void changeInt(int x)
{
   x = x   1;
}
  

приведенный выше код выведет 4, потому что он передается по значению

 class SomeClass
    {
       int x;
    }

void someMethod()
    {
       SomeClass value = new SomeClass();
       value.x = 4;
       changeCls(value);
       System.out.printlin(value.x); 
    }

    public void changeCls(SomeClass cls)
    {
        cls = new SomeClass();
        cls.x = 5;
    }
  

Приведенный выше код все равно будет печатать 4, потому что объект передается по значению, а ссылка на объект передается здесь, даже если он изменен внутри метода, он не будет отражать метод ‘someMethod’.

 class SomeClass
{
   int x;
}

void someMethod()
    {
       SomeClass value = new SomeClass();
       value.x = 4;
       changeCls(value);
       System.out.printlin(value.x); 
    }

    public void changeCls(SomeClass cls)
    {
        cls.x = cls.x   1;
    }
  

здесь также передается объект по значению, и это значение будет ссылкой на объект. Поэтому, когда вы изменяете какое-либо поле этого объекта, оно будет отражаться во всех местах, где упоминается объект. Следовательно, он будет печатать 5. Таким образом, это может быть способ, который вы можете использовать, чтобы делать то, что вы хотите. Инкапсулируйте значение в объект и передайте его методу, в котором вы хотите его изменить.

Ответ №4:

Я запустил некоторые из различных сценариев, описанных выше.

Да, если вы хотите изменить значение вне функции, не возвращая тот же примитив, вам нужно будет передать ему единый единичный массив этого примитива. ОДНАКО в Java все массивы являются внутренними объектами. Пожалуйста, обратите внимание, что если вы передаете ‘value’ по имени в println() файл, ошибка компиляции отсутствует, и он печатает хэши из-за toString() встроенного в класс внутреннего массива. Вы заметите, что эти имена меняются по мере их печати (поместите их в длинный цикл и наблюдайте). К сожалению, Java не поняла, что нам нужно защищенное, но физически статическое адресное пространство, доступное нам по определенным причинам. Однако это повредило бы механизмам безопасности Java. Тот факт, что мы не можем зависеть от известных адресов, означает, что это сложнее взломать. Производительность Java фантастическая, потому что у нас быстрые процессоры. Если вам нужно быстрее или меньше, это для других языков. Я помню это еще с 1999 года, когда читал статью в Dobbs как раз об этом аргументе. Поскольку это веб-язык, предназначенный для работы в Интернете, это была большая уступка безопасности. Ваш КОМПЬЮТЕР в 1999 году имел от 64 МБ до 256 МБ оперативной памяти и работал с частотой около 800 МГц Сегодня, ваше мобильное устройство имеет в 2-8 раз больше оперативной памяти, работает на 200-700 МГц быстрее и выполняет намного больше операций за такт, а Java является предпочтительным языком для Android, доминирующей ОС по объему продаж (iOS все еще качается,я должен когда-нибудь изучить Objective C, я думаю, ненавижу синтаксис, который я видел).

Если вы передали int[] вместо int в этот код 5 , вы вернетесь к someMethod() его вызову.


 public void changeInt(int x)
{
   x = x   1;
} 
  

 public void changeInt(int[] x)
{
   x[0]  = 1; 

}
  

Это сбивающий с толку выбор сверху. Код РАБОТАЛ БЫ, если бы автор не скрыл переданную переменную, объявив локальную переменную с тем же именем. КОНЕЧНО, это не сработает, игнорируйте следующий пример, приведенный выше для ясности.


   public void changeCls(SomeClass cls)
   {
       cls = new SomeClass();
       cls.x = 5;
   }
  

Приведенный выше код все равно будет печататься 4 , потому что переданный объект СКРЫТ ИЗ ОБЛАСТИ ВИДИМОСТИ локальным объявлением. Кроме того, это внутри метода, поэтому я думаю, что даже вызов this и super не прояснит это должным образом.


Если бы он не был скрыт локально в методе, то это изменило бы значение объекта, переданного извне.

Ответ №5:

Для выполнения изменения примитивной переменной в методе существует 2 основных варианта :

1) Если вы хотите изменить значения примитива в другом методе, вы можете обернуть примитив в объект «java bean», который будет по сути похож на указатель.

Или

2) Вы можете использовать класс AtomicInteger / AtomicLong, которые используются для параллелизма, когда многим потокам может потребоваться изменить variable….so переменные должны иметь согласованное состояние. Эти классы переносят примитивы для вас.

Предупреждение: обычно вам лучше возвращать новое значение, а не устанавливать / редактировать его внутри метода, с точки зрения удобства обслуживания..

Ответ №6:

Java — это передача по значению, что означает передачу по копии. Мы не можем выполнять арифметику для ссылочной переменной, как в C . Короче говоря, Java — это не C / C . Итак, в качестве обходного пути вы можете сделать это:

 public static void main (String [] args) {
    int myInt = 4;
    myInt = makeAThree(myInt);

}
static int makeAThree(int n)
{
   return n = 3;
}
  

PS Просто создал метод static так, чтобы использовать его без объекта класса. Никаких других намерений. 😉

Это поможет вам лучше понять.

Ответ №7:

Один из быстрых способов добиться имитации передачи по ссылке — переместить аргументы в переменные-члены включающего класса.

Хотя существует несколько способов сделать это, например, использовать оболочку класса или массива или переместить их в возвращаемый тип функции, код может оказаться не совсем чистым. Если вы похожи на меня, причина задать такой вопрос заключается в том, что часть кода Java уже была закодирована на C (что не работает), и требуется быстрое исправление. Например, в программе рекурсии, такой как поиск в глубину, нам может потребоваться сохранить несколько переменных в списке аргументов функции рекурсии C , таких как путь поиска, которые указывают, должен ли поиск завершиться. Если вы находитесь в такой ситуации, самое быстрое решение — превратить эти переменные аргументов в переменные-члены класса. Позаботьтесь о жизненном цикле переменной и при необходимости сбросьте их значения.

Ответ №8:

Java использует передачу по значению для всего.

Насколько я понимаю, вы не совсем уверены, можете ли вы изменить переданную переменную.

Когда вы передаете объект в метод, и если вы используете этот объект в этом методе, вы фактически модифицируете этот объект. Однако вы изменяете этот объект в его копии, которая по-прежнему указывает на тот же объект. Итак, на самом деле, когда вы передаете объект методу, вы можете его изменить.

Еще раз, все в java передается по значению.точка.