Java에서 매개 변수 전달 메커니즘으로서의 값에 의한 전달

1. 소개

메서드에 인수를 전달하는 가장 일반적인 두 가지 모드는 "값에 의한 전달"및 "참조에 의한 전달"입니다. 다른 프로그래밍 언어는 이러한 개념을 다른 방식으로 사용합니다. Java에 관한 한 모든 것이 엄격하게 Pass-by-Value 입니다.

이 자습서에서는 Java가 다양한 유형에 대한 인수를 전달하는 방법을 설명합니다.

2. 값에 의한 전달과 참조에 의한 전달

함수에 매개 변수를 전달하기위한 몇 가지 다른 메커니즘부터 시작하겠습니다.

  • 참고
  • 결과
  • 가치 결과
  • 이름

최신 프로그래밍 언어에서 가장 일반적인 두 가지 메커니즘은 "값별 전달"및 "참조 별 전달"입니다. 계속하기 전에 먼저 이에 대해 논의 해 보겠습니다.

2.1. 값에 의한 전달

매개 변수가 값에 의한 전달 인 경우 호출자와 피 호출자 메소드는 서로의 사본 인 두 개의 서로 다른 변수에서 작동합니다. 하나의 변수를 변경해도 다른 변수는 수정되지 않습니다.

즉, 메서드를 호출하는 동안 호출 수신자 메서드에 전달 된 매개 변수는 원래 매개 변수의 복제본이됩니다. 호출 수신자 메서드에서 수행 된 수정은 호출자 메서드의 원래 매개 변수에 영향을주지 않습니다.

2.2. 참조에 의한 전달

매개 변수가 참조에 의한 전달이면 호출자와 피 호출자가 동일한 객체에서 작동합니다.

이는 변수가 참조에 의한 전달 일 때 객체의 고유 식별자가 메서드로 전송 됨을 의미합니다 . 매개 변수의 인스턴스 멤버를 변경하면 원래 값이 변경됩니다.

3. 자바에서 매개 변수 전달

모든 프로그래밍 언어의 기본 개념은 "값"과 "참조"입니다. Java에서 Primitive 변수는 실제 값을 저장하는 반면 Non-Primitive는 참조하는 객체의 주소를 가리키는 참조 변수를 저장합니다. 값과 참조는 모두 스택 메모리에 저장됩니다.

Java의 인수는 항상 값으로 전달됩니다. 메서드 호출 중에 값 또는 참조인지 여부에 관계없이 각 인수의 복사본이 스택 메모리에 생성 된 다음 메서드에 전달됩니다.

프리미티브의 경우 값은 단순히 스택 메모리 내부에 복사 된 다음 호출 수신자 메서드로 전달됩니다. 프리미티브가 아닌 경우 스택 메모리의 참조는 힙에있는 실제 데이터를 가리 킵니다. 객체를 전달할 때 스택 메모리의 참조가 복사되고 새 참조가 메서드에 전달됩니다.

이제 몇 가지 코드 예제의 도움을 받아이 작업을 살펴 ​​보겠습니다.

3.1. 기본 유형 전달

Java 프로그래밍 언어에는 8 개의 기본 데이터 유형이 있습니다. 원시 변수는 스택 메모리에 직접 저장됩니다. 기본 데이터 유형의 변수가 인수로 전달 될 때마다 실제 매개 변수가 형식 인수로 복사되고 이러한 형식 인수는 스택 메모리에 자체 공간을 축적합니다.

이러한 형식 매개 변수의 수명은 해당 메서드가 실행되는 동안 만 지속되며 반환시 이러한 형식 인수는 스택에서 삭제되고 폐기됩니다.

코드 예제를 통해 이해해 보겠습니다.

public class PrimitivesUnitTest { @Test public void whenModifyingPrimitives_thenOriginalValuesNotModified() { int x = 1; int y = 2; // Before Modification assertEquals(x, 1); assertEquals(y, 2); modify(x, y); // After Modification assertEquals(x, 1); assertEquals(y, 2); } public static void modify(int x1, int y1) { x1 = 5; y1 = 10; } } 

이러한 값이 메모리에 저장되는 방식을 분석하여 위 프로그램의 주장을 이해해 보겠습니다.

  1. main 메소드 의 변수 " x" 및 " y" 는 기본 유형이며 해당 값은 스택 메모리에 직접 저장됩니다.
  2. modify () 메서드를 호출하면 이러한 각 변수에 대한 정확한 복사본이 생성되어 스택 메모리의 다른 위치에 저장됩니다.
  3. 이러한 복사본에 대한 수정은 복사본에만 영향을 미치며 원래 변수는 변경되지 않습니다.

3.2. 객체 참조 전달

Java에서 모든 객체는 내부적으로 힙 공간에 동적으로 저장됩니다. 이러한 개체는 참조 변수라고하는 참조에서 참조됩니다.

Primitive와 달리 Java 객체는 두 단계로 저장됩니다. 참조 변수는 스택 메모리에 저장되고 참조하는 개체는 힙 메모리에 저장됩니다.

개체가 인수로 전달 될 때마다 원본 참조 변수와 힙 메모리에서 개체의 동일한 위치를 가리키는 참조 변수의 정확한 복사본이 생성됩니다.

그 결과 메서드에서 동일한 객체를 변경할 때마다 해당 변경 사항이 원래 객체에 반영됩니다. 그러나 전달 된 참조 변수에 새 개체를 할당하면 원래 개체에 반영되지 않습니다.

코드 예제를 통해 이것을 이해해 봅시다 :

public class NonPrimitivesUnitTest { @Test public void whenModifyingObjects_thenOriginalObjectChanged() { Foo a = new Foo(1); Foo b = new Foo(1); // Before Modification assertEquals(a.num, 1); assertEquals(b.num, 1); modify(a, b); // After Modification assertEquals(a.num, 2); assertEquals(b.num, 1); } public static void modify(Foo a1, Foo b1) { a1.num++; b1 = new Foo(1); b1.num++; } } class Foo { public int num; public Foo(int num) { this.num = num; } }

위 프로그램에서 주장을 분석 해보자. 동일한 값 1 을 가진 modify () 메서드 에서 ab 객체를 전달했습니다 . 처음에 이러한 개체 참조는 힙 공간에서 두 개의 개별 개체 위치를 가리 킵니다.

이러한 참조 abmodify () 메서드에 전달 되면 동일한 이전 객체를 가리키는 해당 참조 a1b1 의 미러 복사본을 만듭니다 .

에서 수정 () 에있어서, 우리는 기준 수정하면 (A1)을 , 원래의 객체를 변경한다. 그러나 참조 b1의 경우 새 개체를 할당했습니다. 따라서 이제 힙 메모리의 새 개체를 가리키고 있습니다.

b1에 대한 변경 사항은 원래 객체의 내용을 반영하지 않습니다.

4. 결론

이 기사에서는 Primitive와 Non-Primitive의 경우 매개 변수 전달이 어떻게 처리되는지 살펴 보았습니다.

Java에서 매개 변수 전달은 항상 값에 의한 전달이라는 것을 배웠습니다. 그러나 컨텍스트는 Primitives 또는 Objects를 다루는 지에 따라 변경됩니다.

  1. 기본 유형의 경우 매개 변수는 값에 의한 전달입니다.
  2. 객체 유형의 경우 객체 참조는 값에 의한 전달입니다.

이 기사에서 사용 된 코드 조각은 GitHub에서 찾을 수 있습니다.