on
Call By Value, Call By Reference 그리고 자바의 메모리 구조
Call By Value, Call By Reference 그리고 자바의 메모리 구조
반응형
자바 Call By Value, Call By Reference
1. 무엇인가?
메서드에 매개변수를 전달하는 방식에 대한 내용
Call By Value : 값에 의한 호출 매개변수로 받은 값을 복사해서 사용
java에서는 Local Variable Array에 저장 Call By Reference : 참조에 의한 호출 매개변수가 전달될 때 참조값이 전달됨 Call By Assignment Parameter로 전달받는 객체에 따라 객체의 참조방식이 결정된다는 의미
Mutable Object 는 Call by reference의 형태로 참조형으로 변수를 다루며 Immutable Object는 Call by value 의 형태로 변수를 핸들링한다.
2. 기초지식
Stack Memory stack 자료구조 방식으로 관리하는 메모리 구조
Stack Frame이 POP되거나 PUSH됨
메서드가 실행될 때 마다 Stack Frame이 push되고 메서드 종료되면 pop Stack Frame Local Variable Array : 로컬 변수 정보를 저장하는 배열(arguments 포함)
Operand Stack : 명령어들은 하나 씩 실행시키며 중간 연산결과를 일시적으로 저장
Frame Data : 메서드 관련 정보(이전 메서드로 돌아올 위치, 메서드 반환값 등) Method Area : JVM이 자바코드를 실행하기 위한 정보를 저장 Class 정보, interface정보, Field 정보, 메서드 정보, 정적 메서드 정보, 생성자 정보, 정적 변수 등
정적변수에 저장되는 값이 인스턴스면 heap, 수 리터럴이면 Runtime Constant Pool, 문자열은 String Constant Pool(heap)
정적변수는 인스턴스, 문자열과는 다른 메모리 공간에 저장된다. Heap new로 생성된 인스턴스 등이 저장되는 영역
3. Java에서 파라미터 전달은 Call By Value인가 Call By Reference인가?
Call By Value도 Call By Reference도 있다.
Call By Value 기본자료형의 경우
참조자료형이면서 다른 메모리 공간인 경우 Call By Reference 참조자료형이면서 메모리 공간을 공유하는 경우
4. 예제
@Test void run() { // Stack Frame run() Fruit grape = new Fruit("포도", 1); Fruit apple = new Fruit("사과", 2); System.out.println("grape : " + grape); System.out.println("apple : " + apple); // run()과 swap()은 다른 Stack Frame swap(grape, apple); System.out.println("grape : " + grape); System.out.println("apple : " + apple); // grape : SecurityApplicationTests.Fruit(name=포도, number=1) // apple : SecurityApplicationTests.Fruit(name=사과, number=2) // grape : SecurityApplicationTests.Fruit(name=포도, number=1) // apple : SecurityApplicationTests.Fruit(name=사과, number=2) } private static void swap(Fruit a, Fruit b) { // Stack Frame swap() // swap()의 Local Variables Array에 담긴 참조값의 위치들만 바꼈기 때문에 // run()에는 영향을 주지 않는다. Fruit temp = a; a = b; b = temp; } @AllArgsConstructor @ToString public class Fruit { public String name; public Integer number; }
@Test void runInteger() { // Stack Frame runInteger() Fruit grape = new Fruit("포도", 1); Fruit apple = new Fruit("사과", 2); // wrapper class 변수가 인스턴스 또는 클래스의 필드인 경우 : 힙에 존재 // 힙 영역은 공유되므로 덧셈연산이 힙 메모리에 있는 데이터에 영향을 준다. System.out.println("grape : " + grape); System.out.println("apple : " + apple); addNumber(grape); System.out.println("grape : " + grape); System.out.println("apple : " + apple); // grape : SecurityApplicationTests.Fruit(name=포도, number=1) // apple : SecurityApplicationTests.Fruit(name=사과, number=2) // grape : SecurityApplicationTests.Fruit(name=포도, number=2) // apple : SecurityApplicationTests.Fruit(name=사과, number=2) // wrapper class 변수가 지역 변수인 경우: 스택에 존재 // number는 new Integer로 생성되었지만 지역변수이므로 스택에 존재한다. // addNumber와는 다른 메모리 공간에 있기 때문에 덧셈연산이 안된다. Integer number = 10; System.out.println("number : " + number); addNumber(number); System.out.println("number : " + number); // number : 10 // number : 10 } private static void addNumber(Fruit fruit) { fruit.number++; } private static void addNumber(Integer integer) { integer++; }
참고
코드라떼 https://www.youtube.com/watch?v=m9lv_Zt7otk&list;=TLPQMTIwOTIwMjG-43HqL76-Tw&index;=3
코드라떼 https://www.youtube.com/watch?v=Vd1C3-wHc4Y&t;=244s
생활코딩 https://opentutorials.org/course/1223/6339
반응형
from http://dotheright.tistory.com/359 by ccl(A) rewrite - 2021-09-12 15:01:02