[Java] 함수 호출 방식 call by value & call by reference

ina·2022년 8월 31일
0
post-thumbnail

함수 호출 방식 (Call by Value / Call by Reference)

  • 함수에 인자를 전달하는 방식에는 크게 두가지가 있다
  • Call by Value(값에 의한 호출)
    • 기본 자료형 : call by value로 동작 (int, short, long, float, double, char, boolean)
    • Java의 경우, 항상 call by value로 값을 전달한다
      // Call by Value
      public class Cup {
      
      	static void pourCoffee(int cup, int americano) {
      		cup += americano;
      	}
      	
      	public static void main(String[] args) {
      		int cup = 0;
      		int americano = 10;
      		
      		System.out.println("컵의 양: "+ cup + "리터");
      		
      		// 컵에 아메리카노 채우기
      		pourCoffee(cup, americano);
      		
      		// 이후 컵에 담긴 아메리카노의 양
      		System.out.println("call by value 컵의 양: "+ cup + "리터");
      	}
      
      }
      
      // 결과
      // 컵의 양 : 0리터
      // call by value 컵의 양 : 0리터
    • 함수가 호출 시 메모리 공간 안에서 별도의 임시 공간이 생성한다 ⇒ 함수 종료시 반환한다
    • 함수 호출 시 전달되는 변수 값을 복사해서 함수 인자로 전달한다
    • 복사된 인자는 함수 안에서 지역적으로 사용 ⇒ local value 속성을 가진다
    • 장점
      • 복사하여 처리하기 때문에 안전하다. 원래의 값이 보존된다
      • 함수 안에서 인자 값이 변경되더라도, 외부 변수 값은 변경되지 않는다
    • 단점
      • 복사를 하기 때문에 메모리 사용량이 늘어난다 (과부화의 원인)
  • Call by Reference(참조에 의한 호출)
    • 참조 자료형 : call by reference로 동작 (Array, Class instance)

    • 함수 호출 시 인자로 전달되는 변수의 레퍼런스를 전달한다

      // Call by Reference
      public class Cup {
      	int cup = 0;
      	
      	Cup(int cup){
      		this.cup = cup;
      	}
      	
      	static void pourCoffee(Cup cup, int americano) {
      		cup.cup += americano;
      	}
      	
      	public static void main(String[] args) {
      		int americano = 10;
      		Cup cup = new Cup(0);
      		System.out.println("컵의 양: "+ cup.cup + "리터");
      		System.out.println("컵의 양: "+ cup + "리터"); // 객체주소가 참조되어진 것을 확인할 수 있다
      	
      		// 컵에 아메리카노 채우기
      		pourCoffee(cup, americano);
      		
      		// 이후 컵에 담긴 아메리카노의 양
      		System.out.println("call by reference 컵의 양: "+ cup.cup + "리터");
      		System.out.println("call by reference 컵의 양: "+ cup + "리터"); // 객체주소가 참조되어진 것을 확인할 수 있다
      	}
      }
      
      // 결과
      // 컵의 양 : 0리터
      // call bt reference 컵의 양 : 10리터
    • 장점

      • 복사하지 않고 직접 참조를 하기에 빠르다
    • 단점

      • 직접 참조를 하기에 원래 값이 영향을 받는다(리스크)
  • 정리
    • 값을 복사를 하여 처리 → Call by Value
      • 원래의 값이 보존
    • 직접 참조를 하여 처리 → Call by Reference
      • 원래의 값이 영향을 받음


https://dreamcoding.tistory.com/10

package java_test;

// Call by Value
//public class Cup {
//
//	static void pourCoffee(int cup, int americano) {
//		cup += americano;
//	}
//	
//	public static void main(String[] args) {
//		int cup = 0;
//		int americano = 10;
//		
//		System.out.println("컵의 양: "+ cup + "리터");
//		
//		// 컵에 아메리카노 채우기
//		pourCoffee(cup, americano);
//		
//		// 이후 컵에 담긴 아메리카노의 양
//		System.out.println("call by value 컵의 양: "+ cup + "리터");
//	}
//
//}

/* 
 * 컵에 아메리카노를 담는다는 상황을 가정한 코드이다
 * 커피를 붓는 메소드인 pourCoffee메소드를 사용하면 컵의 양이 10리터 만큼 늘어난 양이 나와야 한다
 * 그런데 커피를 부었는데 여전히 컵의 양은 0이다
 * 컵과 아메리카노 양에 대한 값만 복사해서 가져온 것이라 실질적인 컵과 아메리카노의 양에는 영향을 끼치지 못한
 */

// Call by Reference
public class Cup {
	int cup = 0;
	
	Cup(int cup){
		this.cup = cup;
	}
	
	static void pourCoffee(Cup cup, int americano) {
		cup.cup += americano;
	}
	
	public static void main(String[] args) {
		int americano = 10;
		Cup cup = new Cup(0);
		System.out.println("컵의 양: "+ cup.cup + "리터");
	
		// 컵에 아메리카노 채우기
		pourCoffee(cup, americano);
		
		// 이후 컵에 담긴 아메리카노의 양
		System.out.println("call by reference 컵의 양: "+ cup.cup + "리터");
	}
}

/*
 * 생성자로 컵을 생성하여 컵을 객체화해서 컵을 생성시 하나의 주소값을 가지고 있도록 했다
 * 이후 객체화된 컵에 앙메리카노를 부으면 객체화되어 주소값을 가진 컵 객체의 주소값을 참조하여
 * 아메리카노를 붓기 때문에 나중에 확인하면 참조한 컵에 부었기 때문에 값이 추가되어 나타난다 
*/

참고 자료 :
Java 의 Call by Value, Call by Reference
[Java] 함수 호출 'CallByValue' 와 'CallByReference' 의 차이
Call by value vs Call by Reference

profile
🐢 💨 💨

0개의 댓글