🥥

JAVA: Pass by Value or Reference

자바에서 함수(Method/Function)에 변수를 전달하고자 한다. 이때 전달하는 것은 변수의 값일까 아니면 변수를 참조(Reference)일까. 답은 변수의 값이다. 자바에서는 변수를 전달할 때, 값을 전달(Pass by Value)한다. 

간단하게 아래 예제를 보자.

123456789101112131415161718
class Main {
public static void main(String[] args) throws Exception {
long nothing = 1L;
System.out.println("main method, nothing: " + nothing);
doSomething(nothing);
System.out.println("main method, nothing: " + nothing);
}
private static void doSomething(long something) {
System.out.println("doSomething method, something: " + something);
something = 999L;
System.out.println("doSomething method, something: " + something);
}
}

nothing 이라는 변수를 초기화한 후, doSomething() 함수를 호출했다. 이 함수는 매개변수인 something 이라는 변수에 다른 값을 할당한다. doSomething() 함수가 반환된 이후, nothing 의 값은 얼마일까, 답은 여전히 초기 값이 1이다. nothing 이라는 변수의 값이 매개 변수인 something 으로 전달하고, something 에 다른 값을 할당한다 해도 nothing 에는 아무런 영향을 주지 않는다.

01

그러나 한 가지 주의할 부분이 있다. 바로 객체를 매개 변수로 전달할 때다. 객체를 전달할 때는 객체의 값 전체를 전달하는 것이 아니라 객체를 참조하는 주소 값을 전달한다. 여기서의 주소 값은 객체에 할당된 메모리 주소가 아니라 객체를 참조할 수 있는 어떤 임의 값이라고 생각하자. 객체의 주소 값을 전달하기 때문에 전달 받은 안의 함수에서 객체를 사용할 때 주의해야 한다. 아래 또 다른 예제를 살펴보자.

1234567891011121314151617181920212223242526272829303132
class Main {
public static void main(String[] args) throws Exception {
Everything nothing = new Everything();
nothing.setThing(1L);
System.out.println("main method, nothing: " + nothing.getThing());
doSomething(nothing);
System.out.println("main method, nothing: " + nothing.getThing());
}
private static void doSomething(Everything something) {
System.out.println("doSomething method, something: " + something.getThing());
something.setThing(999L);
System.out.println("doSomething method, something: " + something.getThing());
}
static class Everything {
long thing;
public void setThing(long thing) {
this.thing = thing;
}
public long getThing() {
return thing;
}
}
}

Everything 이라는 임의의 클래스를 만들고 nothing 이라는 객체를 초기화했다. 그리고 이전 예제처럼 doSomething() 함수를 호출하고 이 함수 내에서 Everything.setThing() 함수를 이용하여 값을 할당했다. doSomething() 함수가 반환된 이후, nothing 의 값은 999로 변경된다. 즉, doSomething() 안에서 전달 받은 변수인 nothing 을 제어한 셈이다. 객체를 매개 변수로 전달할 때, 새로운 객체를 만들고 그 객체의 전달하는 객체의 값으로 초기화해주지 않는다. 자바에서 매개 변수로 값으로만 전달한다고 생각해서 객체까지 제어할 때 이부분을 간과할 수 있다.

02

마치며

현업에서 위의 특징 때문에 문제가 발생할 수 있다. 특히 entity 객체일 경우, 트랜잭션 안에서 값을 변경하고 dirty check를 통해 자동으로 데이터베이스까지 값이 변경이 되기 때문이다. Entity에 대한 값 변경이 자유롭다면 유지보수 하기 너무 힘들 것이다. 이러한 부분을 미연에 방지하고자 객체의 값을 변경하는 함수를 엄격하게 제어하는 것은 어떨까.