Как передать параметр
Перейти к содержимому

Как передать параметр

  • автор:

Передача параметров по ссылке и по значению при вызове процедур и функций

Внимание! Материал данной статьи устарел. Рекомендуется использовать документацию к платформе «1С:Предприятие 8».

Встроенный язык 1С:Предприятия поддерживает два способа передачи параметров в процедуры и функции: передача параметров по ссылке и передача параметров по значению.

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

По умолчанию, во встроенном языке 1С:Предприятия 8 передача параметров в процедуры и функции осуществляется по ссылке. Это означает, что изменение формального параметра внутри процедуры или функции будет отражаться на значении фактического параметра, переданного при вызове процедуры или функции.

Процедура Процедура1(ФормальныйПараметр1) ФормальныйПараметр1 = 2 * 3; КонецПроцедуры ФактическийПараметр = 10; Процедура1(ФактическийПараметр); // будет выведено значение 6 - изменение формального // параметра внутри процедуры повлияло на изменение // значения фактического параметра, переданного при // вызове процедуры: по умолчанию, параметры передаются // по ссылке! Сообщить(ФактическийПараметр);

Передача параметров по значению

При передаче параметра вызываемой процедуры или функции по значению, изменение значения формального параметра внутри процедуры или функции никак не влияет на фактический параметр, передаваемый при вызове процедуры или функции. Указание, что параметр нужно передавать по значению, осуществляется с помощью ключевого слова Знач .

Процедура Процедура2(Знач ФормальныйПараметр1) ФормальныйПараметр1 = 2 * 3; КонецПроцедуры ФактическийПараметр = 10; Процедура2(ФактическийПараметр); // будет выведено значение 10 - изменение формального // параметра внутри процедуры НЕ повлияло на изменение // значения фактического параметра, переданного при // вызове процедуры: параметр передан по значению! Сообщить(ФактическийПараметр);

Особенности передачи переменных различных типов данных по значению

Передача переменных различных типов данных по значению имеет свои особенности. Они заключаются в том, что при работе с методами и свойствами контекста формальных параметров может изменяться состояние фактического параметра, передаваемого при вызове процедуры или функции.

Рассмотрим в качестве примера ситуацию, когда параметром процедуры, передаваемым по значению, является таблица значений. Внутри вызываемой процедуры ОбработатьТаблицу() создается новый экземпляр таблицы значений, в который добавляется три строки. Это никак не влияет на состояние таблицы значений Тз , переданной в качестве фактического параметра при вызове процедуры ОбработатьТаблицу() :

// Указано, что передача параметра ТаблЗнач осуществляется по значению Процедура ОбработатьТаблицу(Знач ТаблЗнач) // Создадим новую таблицу значений ТаблЗнач = Новый ТаблицаЗначений; // Добавим в таблицу значений две колонки ТаблЗнач.Колонки.Добавить("Колонка1"); ТаблЗнач.Колонки.Добавить("Колонка2"); // Добавим несколько строк в таблицу значений Для п = 1 По 3 Цикл НовСтрока = ТаблЗнач.Добавить(); НовСтрока.Колонка1 = "Колонка"; НовСтрока.Колонка2 = п; КонецЦикла; КонецПроцедуры // Создадим новую таблицу значений Тз = Новый ТаблицаЗначений; // Добавим в таблицу значений три колонки Тз.Колонки.Добавить("Колонка1"); Тз.Колонки.Добавить("Колонка2"); Тз.Колонки.Добавить("Колонка3"); // Добавим несколько строк в таблицу значений Для п = 1 По 10 Цикл НовСтрока = Тз.Добавить(); НовСтрока.Колонка1 = "Колонка1"; НовСтрока.Колонка2 = "Колонка2"; НовСтрока.Колонка3 = п; КонецЦикла; // будет выведено значение 10 Сообщить("Число элементов в ТЗ до обработки: " + Тз.Количество()); // Вызовем процедуру, передав фактический параметр Тз по значению ОбработатьТаблицу(Тз); // будет выведено значение 10: внутри процедуры ОбработатьТаблицу // в формальный параметр сохранили новую таблицу значений Сообщить("Число элементов в ТЗ после обработки: " + Тз.Количество());

Рассмотрим в качестве примера ситуацию, когда параметром процедуры, передаваемым по значению, является таблица значений. Внутри вызываемой процедуры СвернутьТаблицу() таблица значений, переданная в качестве параметра при вызове процедуры, сворачивается:

// Указано, что передача параметра ТаблЗнач осуществляется по значению Процедура СвернутьТаблицу(Знач ТаблЗнач) // Свернем таблицу значений по колонкам Колонка1 и Колонка3 ТаблЗнач.Свернуть("Колонка1", "Колонка3"); КонецПроцедуры // Создадим новую таблицу значений Тз = Новый ТаблицаЗначений; // Добавим в таблицу значений три колонки Тз.Колонки.Добавить("Колонка1"); Тз.Колонки.Добавить("Колонка2"); Тз.Колонки.Добавить("Колонка3"); // Добавим несколько строк в таблицу значений Для п = 1 По 10 Цикл НовСтрока = Тз.Добавить(); НовСтрока.Колонка1 = "Колонка1"; НовСтрока.Колонка2 = "Колонка2"; НовСтрока.Колонка3 = п; КонецЦикла; // будет выведено значение 10 Сообщить("Число элементов в ТЗ до сворачивания: " + Тз.Количество()); // Вызовем процедуру, передав фактический параметр Тз по значению СвернутьТаблицу(Тз); // Таблица значений теперь свернута: будет выведено значение 1 Сообщить("Число элементов в ТЗ после сворачивания: " + Тз.Количество());

Схематично изобразить происходящее при вызове процедуры СвернутьТаблицу(Тз) можно следующим образом:

(1) — вызов процедуры СвернутьТаблицу . В качестве фактического параметра указывается переменная Тз, хранящая ссылку на экземпляр таблицы значений;

(2) — из процедуры вызывается метод Свернуть таблицы значений;

(3) — формальный параметр ссылается на тот же самый экземпляр таблицы значений, что и фактический параметр (переменная Тз) — происходит свертка в экземпляре таблицы значений, на которую ссылается переменная Тз;

(4) — выходим из процедуры. Экземпляр таблицы значений, на которую ссылается переменная Тз, находится в свернутом состоянии.

Таким образом, передача фактического параметра по значению в данном случае не привела к созданию копии таблицы значений. При работе со свойствами и методами таблицы значений мы работаем со свойствами и методами той таблицы значений, которая использовалась при вызове процедуры СвернутьТаблицу() .

Разница для всех типов при передаче параметра процедуры или функции по ссылке или по значению проявляется в присвоении фактическому параметру процедуры или функции нового значения. Вызов свойств и методов контекста фактического параметра, если таковые имеются, влияет на формальный параметр независимо от того, передается ли он по ссылке или по значению.

Java: передача параметров по значению или по ссылке

Простое объяснение принципов передачи параметров в Java.

Многие программисты часто путают, какие параметры в Java передаются по значению, а какие по ссылке. Давайте визуализируем этот процесс, и тогда вы увидите насколько все просто.

Данные передаются между методами через параметры. Есть два способа передачи параметров:

  1. Передача по значению (by value). Значения фактических параметров копируются. Вызываемый метод создает свою копию значений аргументов и затем ее использует. Поскольку работа ведется с копией, на исходный параметр это никак не влияет.
  2. Передача по ссылке (by reference). Параметры передаются как ссылка (адрес) на исходную переменную. Вызываемый метод не создает свою копию, а ссылается на исходное значение. Следовательно, изменения, сделанные в вызываемом методе, также будут отражены в исходном значении.

В Java переменные хранятся следующим образом:

  1. Локальные переменные, такие как примитивы и ссылки на объекты, создаются в стеке.
  2. Объекты — в куче (heap).

Теперь вернемся к основному вопросу: переменные передаются по значению или по ссылке?

Java всегда передает параметры по значению

Чтобы разобраться с этим, давайте посмотрим на пример.

Пример передачи примитивов по значению

Поскольку Java передает параметры по значению, метод processData работает с копией данных. Следовательно, в исходных данных (в методе main ) не произошло никаких изменений.

Теперь рассмотрим другой пример:

Передача объекта

Что здесь происходит? Если Java передает параметры по значению, то почему был изменен исходный список? Похоже, что Java все-таки передает параметры не по значению? Нет, неправильно. Повторяйте за мной: «Java всегда передает параметры по значению».

Чтобы с этим разобраться, давайте посмотрим на следующую диаграмму.

Память стека (stack) и кучи (heap)

В программе, приведенной выше, список fruits передается методу processData . Переменная fruitRef — это копия параметра fruit . И fruits и fruitsRef размещаются в стеке. Это две разные ссылки. Но самое интересное заключается в том, что они указывают на один и тот же объект в куче. То есть, любое изменение, которое вы вносите с помощью любой из этих ссылок, влияет на объект.

Давайте посмотрим на еще один пример:

Передача объекта по ссылкеПамять стека (stack) и кучи (heap)

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

Итак, Java всегда передает параметры по значению. Однако мы должны быть осторожны при передаче ссылок на объекты.

Вышеприведенная концепция очень важна для правильного решения ваших задач.

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

Удаление узла в связанном списке

class Node < int data; Node next; Node(int d)< data = d; next = null; >> class LinkedList < public static Node push(Node head, int data) < Node newNode = new Node(data); newNode.next = head; head = newNode; return head; >public static void deleteNode(Node head, int position) < // List is empty if (head == null)< return; >// If position is 1st, removing head node if (position == 1) < head = head.next; return; >Node prevNode = head; int i = 2; while (prevNode != null && i != position) < prevNode = prevNode.next; i++; >// When position is more than number of node if (prevNode == null || prevNode.next == null) < return; >prevNode.next = prevNode.next.next; > public static void printList(Node head) < Node currNode = head; while (currNode != null) < System.out.print(currNode.data + " "); currNode = currNode.next; >> public static void main(String[] args) < Node head = null; head = push(head, 5); head = push(head, 4); head = push(head, 3); head = push(head, 2); head = push(head, 1); System.out.println("Created Linked list is: "); printList(head); // Delete node at position 2 deleteNode(head, 2); System.out.println("\nLinked List after Deletion at position 2: "); printList(head); >> 

Это решение работает во всех случаях, кроме одного — когда вы удаляете первый узел ( Position = 1 ). Основываясь на ранее описанной концепции, видите ли вы в чем здесь проблема? Возможно, поможет следующая диаграмма.

Удаление первого узла односвязного списка

Для исправления алгоритма необходимо сделать следующее:

public static Node deleteNode(Node head, int position) < // List is empty if (head == null)< return head; >// If position is 1st, removing head node if (position == 1) < head = head.next; return head; >Node prevNode = head; int i = 2; while (prevNode != null && i != position) < prevNode = prevNode.next; i++; >// When position is more than number of node if (prevNode == null || prevNode.next == null) < return head; >prevNode.next = prevNode.next.next; return head; > public static void main(String[] args) < Node head = null; head = push(head, 5); head = push(head, 4); head = push(head, 3); head = push(head, 2); head = push(head, 1); System.out.println("Created Linked list is: "); printList(head); // Delete node at position 2 head = deleteNode(head, 2); System.out.println("\nLinked List after Deletion at position 2: "); printList(head); >//Rest of the code remains same 

В этой статье мы обсудили одну небольшую, но важную концепцию Java: передачу параметров.

Перевод статьи подготовлен в преддверии старта курса «Подготовка к сертификации Oracle Java Programmer (OCAJP)».

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

ЗАПИСАТЬСЯ НА ВЕБИНАР

  • Блог компании OTUS
  • Программирование
  • Java

Как передать параметр в метод

Вопрос следующий. У нас есть метод, который открывает окно оплаты, первым аргументом мы передаем сумму, а вторым нужно передать источник оплаты. Можно было бы передать просто строку. Но как я понимаю, правильно было бы передать параметр.

 public partial class Pay : Form < private Context Context = new Context(); public Pay() < InitializeComponent(); >public static DialogResult Open(decimal Amount, PaySource Source) < var form = new Pay(); form.ShowDialog(); return form.DialogResult; >> public struct PaySource

Как мне правильно сделать так, что бы я мог сделать так.

Pay.Open(666, PaySource.FromWorkShop) 
Pay.Open(666, PaySource.FromKassa) 

То есть это должно быть что то вроде

System.Drawing.Color.Red 

Передача параметров в Java

Java-университет

Переменная в Java — это контейнер, со значением в нем. Так что значит «передать» переменную? И какова разница между примитивными и ссылочными типами данных.

Передача параметров в Java - 1

Мы доберемся до этого позже. Давайте сначала начнем с простого присваивания. Что делает данный код:

 int х = 3; int у = х; 

В строке 1 создается переменная x типа int и ей присваивается значение 3. В строке 2, создается переменная y типа int и ей присвается значение переменной x. В дальнейшем переменная x никак не влияет на y. Java копирует значение х (3) и помещает эту копию в у. Это передача параметра по значению. Вы не записываете одну переменную в другую. Значение копируется и присваивается новой переменной. Выражение у = х; НЕ означает «записать x в y«. Оно означает «скопировать значение внутри х и записать эту копию в у«. Если позже я изменю y:

 у = 34; 

Повлияет ли это на x? Конечно нет. x по прежнему имеет значение 3. Если позже я изменю х:

 х = 90; 

Как это отразится на y? Никак. Они никак не связаны после того, как было сделано присвоение (КОПИРОВАНИЕ значения). А что насчет ссылочных типов? Как они работают? Не так уж сложно, на самом деле это правило то же самое. Ссылки делают тоже самое — вы получаете копию ссылки. Так что, если я говорю:

 Cat A = new Cat (); Cat B = A; 

Ссылка А копируется в ссылку B. К объекту это не относится — у вас по прежнему всего один объект. Но теперь у вас есть две различных ссылки, контролирующие один и тот же объект Cat. Теперь давайте рассмотрим передачу параметров в методы. Java передает параметры по значению. Всегда. Это означает — «скопировать значение и передать копию.» Для примитивных типов это легко:

 int х = 5; doStuff (х); / / Передать копию х (значение 5) в метод doStuff 

Метод doStuff выглядит следующим образом:

 void doStuff (int у) < / / Действия с 'y' >

Копия значения x, тоесть 5, передается в метод doStuff (). Метод doStuff () имеет свою собственную переменную, которая называется y. Переменная y — новая, другая переменная. С копией того, что было в х на момент передачи его в метод. С этого момента, у и х не влияют друг на друга. При изменении у, вы не затрагиваете х.

 void doStuff (int у) < у = 27; / / Это не влияет на 'х' >

И наоборот — при изменении х, вы не измените y. Единственное что сделал x в этом деле это скопировал свое значение и передал его в метод doStuff(). Как «передача по значению» работает со ссылками? Слишком многие люди говорят, «Java передает примитивные типы по значению, а объекты по ссылке». Это не так как говорят. Java передает все по значению. С примитивами, вы получаете копию содержимого. Со ссылками вы тоже получаете копию содержимого. Но что такое содержимое ссылки? Пульт дистанционного управления. Средства для управления / доступа к объекту. Когда вы передаете ссылку на объект в метод, вы передаете копию ссылки. Клон пульта дистанционного управления. Объект все еще сидит в куче где был создан, ожидая кого-то, чтобы использовали пульт. Объект не волнует сколько пультов «запрограммированы» чтобы контролировать его. Это волнует только сборщика мусора и вас, программиста. Поэтому, когда вы говорите:

 Cat A = new Cat (); doStuff (А); void doStuff (Cat B) < / / Использование B >

Существует только один объект Cat. Но теперь два пульта управления (ссылки) могут получить доступ к одному и тому же объекту Cat. Так что теперь все, что B делает объекту Cat, повлияет на Cat, на который указывает A, но это не повлияет на содержимое A! Вы можете изменить Cat, используя новую ссылку B (скопированную непосредственно с А), но вы не можете изменить А. Какого черта это значит? Вы можете изменить объект, на который ссылается А, но вы не можете взять и изменить ссылку А — переадресовать её на другой объект или null. Так что если вы измените ссылку B (не сам объект Cat на который ссылается B, а само значение ссылки) вы не измените значение А. И наоборот. Так что:

 Cat A = new Cat (); doStuff (А); void doStuff (Cat B) < B = new Cat (); / / Не повлияет на ссылку A >

Это просто значит, что B указывает на другой объект. A по-прежнему счастлива. Так что повторяйте за мной: Java передает все по значению. (Хорошо, еще раз. с чувством.) Java передает все по значению. Для примитивных типов — вы передаете копию текущего значения, для ссылок на объекты — вы передаете копию ссылки (дистанционного управления). Вы никогда не передаете объект. Все объекты хранятся в куче. Всегда. Теперь заварите здоровенную чашку кофе и пишите код! Оригинал статьи.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *