자바의 매개변수 전달 방식: 값에 의한 전달

2024-08-04

답변: 자바는 값에 의한 전달(pass-by-value) 방식을 사용합니다.

값에 의한 전달이란?

함수(메소드) 호출 시, 실제 매개변수의 값을 복사하여 함수 내의 매개변수에 전달하는 방식입니다. 즉, 함수 내에서 매개변수를 변경하더라도, 호출한 곳의 실제 매개변수 값은 변하지 않습니다.

자바에서 값에 의한 전달이 적용되는 이유

  • 기본형 변수: int, double, char 등의 기본형 변수는 값 자체가 복사되어 전달됩니다.
  • 참조형 변수: 객체의 주소값이 복사되어 전달됩니다. 하지만, 주소값 자체만 복사되기 때문에, 함수 내에서 객체의 내용을 변경하면 원본 객체도 변경됩니다. 마치 참조에 의한 전달처럼 보이지만, 실제로는 주소값이라는 값이 복사된 것이므로 값에 의한 전달입니다.

예시

public class PassByValue {
    public static void changeValue(int x) {
        x = x + 10;
    }

    public static void main(String[] args) {
        int a = 5;
        changeValue(a);
        System.out.println(a); // 출력 결과: 5
    }
}

위 예시에서 changeValue 함수 내에서 x의 값을 변경했지만, main 함수의 a 값은 변하지 않습니다. 이는 a의 값이 복사되어 x에 전달되었기 때문입니다.

참조형 변수의 경우

public class PassByValue {
    public static void changeObject(MyObject obj) {
        obj.value = 100;
    }

    public static void main(String[] args) {
        MyObject obj = new MyObject();
        obj.value = 50;
        changeObject(obj);
        System.out.println(obj.value); // 출력 결과: 100
    }
}

위 예시에서는 obj 객체의 주소값이 복사되어 changeObject 함수의 obj 매개변수에 전달됩니다. 따라서, changeObject 함수 내에서 obj.value를 변경하면 원본 객체의 value 값도 변경됩니다. 하지만, 이는 주소값이라는 값이 복사되었기 때문에 값에 의한 전달의 범주에 속합니다.

결론

자바는 값에 의한 전달 방식을 사용하지만, 참조형 변수의 경우 주소값이 복사되기 때문에 마치 참조에 의한 전달처럼 동작하는 경우가 있습니다. 이러한 특징을 잘 이해하고 프로그래밍해야 예상치 못한 결과를 방지할 수 있습니다.




자바 매개변수 전달 방식 관련 샘플 코드 심층 분석

기본형 변수 (값에 의한 전달)

public class PrimitiveTypeExample {
    public static void changeValue(int x) {
        x = x + 10;
        System.out.println("함수 내 x: " + x); // 함수 내에서만 값이 변경됨
    }

    public static void main(String[] args) {
        int a = 5;
        changeValue(a);
        System.out.println("메인 함수의 a: " + a); // a의 값은 변하지 않음
    }
}
  • 설명:
    • changeValue 함수에 a의 값이 복사되어 전달됩니다.
    • 함수 내에서 x의 값을 변경해도 원본 변수 a에는 영향을 미치지 않습니다.

참조형 변수 (객체, 주소값 전달)

public class ReferenceTypeExample {
    public static void changeObject(MyObject obj) {
        obj.value = 100;
        System.out.println("함수 내 obj.value: " + obj.value); // obj.value 변경
    }

    public static class MyObject {
        int value;
    }

    public static void main(String[] args) {
        MyObject obj = new MyObject();
        obj.value = 50;
        changeObject(obj);
        System.out.println("메인 함수의 obj.value: " + obj.value); // obj.value도 변경됨
    }
}
  • 설명:
    • obj 객체의 주소값이 changeObject 함수로 전달됩니다.
    • 함수 내에서 obj.value를 변경하면 원본 객체의 value 값도 변경됩니다.
    • 주소값이 복사되었기 때문에 값에 의한 전달이지만, 객체의 내용을 변경할 수 있어 참조에 의한 전달처럼 보입니다.

배열 (참조형 변수)

public class ArrayExample {
    public static void changeArray(int[] arr) {
        arr[0] = 100;
        System.out.println("함수 내 arr[0]: " + arr[0]); // arr[0] 변경
    }

    public static void main(String[] args) {
        int[] arr = {50, 60, 70};
        changeArray(arr);
        System.out.println("메인 함수의 arr[0]: " + arr[0]); // arr[0]도 변경됨
    }
}
  • 설명:
    • 배열은 참조형 변수이므로, 배열의 주소값이 함수로 전달됩니다.
    • 함수 내에서 배열의 요소를 변경하면 원본 배열의 요소도 변경됩니다.

String (불변 객체)

public class StringExample {
    public static void changeString(String str) {
        str = "new String";
        System.out.println("함수 내 str: " + str); // str 변경
    }

    public static void main(String[] args) {
        String str = "original";
        changeString(str);
        System.out.println("메인 함수의 str: " + str); // str은 변하지 않음
    }
}
  • 설명:
    • String은 불변 객체입니다.
    • changeString 함수 내에서 str에 새로운 문자열을 할당하면 새로운 String 객체가 생성되고, str 변수는 새로운 객체를 참조하게 됩니다.
    • 원본 String 객체는 변경되지 않습니다.

정리

  • 기본형 변수: 값이 복사되어 전달되므로, 함수 내에서 값을 변경해도 원본 변수에는 영향을 미치지 않습니다.
  • 참조형 변수 (객체, 배열): 주소값이 복사되어 전달되므로, 함수 내에서 객체의 내용을 변경하면 원본 객체도 변경됩니다.
  • String: 불변 객체이므로, 새로운 문자열을 할당해도 원본 문자열은 변경되지 않습니다.

주의:

  • 참조형 변수를 복사하려면: clone() 메소드를 사용하거나 직접 새로운 객체를 생성하여 값을 복사해야 합니다.
  • String을 변경하려면: StringBuilder 또는 StringBuffer 클래스를 사용해야 합니다.
  • 왜 자바는 값에 의한 전달 방식을 사용할까요?
  • 참조형 변수의 얕은 복사와 깊은 복사의 차이점은 무엇일까요?
  • 불변 객체의 장단점은 무엇일까요?



자바에서 값에 의한 전달의 제약을 극복하는 대체 방법

자바는 기본적으로 값에 의한 전달 방식을 사용하기 때문에, 함수 내에서 매개변수를 변경하더라도 원본 값은 변하지 않습니다. 하지만, 때로는 함수 내에서 원본 값을 변경해야 할 필요가 생길 수 있습니다. 이러한 경우 다음과 같은 방법들을 활용할 수 있습니다.

객체 반환

  • 개념: 함수 내에서 원본 객체를 수정한 후, 수정된 객체를 반환합니다.
  • 장점: 직관적이고 간단하게 원본 객체를 변경할 수 있습니다.
  • 예시:
public class ReturnObject {
    public static Person changeAge(Person person) {
        person.age += 1;
        return person;
    }

    public static void main(String[] args) {
        Person p = new Person(30);
        p = changeAge(p);
        System.out.println(p.age); // 출력: 31
    }
}

Wrapper 클래스

  • 개념: 기본형 변수를 객체로 포장하여 참조형처럼 사용합니다.
  • 장점: 기본형 변수를 객체처럼 다룰 수 있어 유연성이 높습니다.
public class WrapperClassExample {
    public static void changeValue(Integer x) {
        x += 10;
    }

    public static void main(String[] args) {
        Integer a = 5;
        changeValue(a);
        System.out.println(a); // 출력: 5 (원본 값은 변하지 않음)
    }
}
  • 주의: Wrapper 클래스는 불변 객체이므로, 값을 변경하려면 새로운 객체를 생성해야 합니다.

배열

  • 개념: 배열은 참조형 변수이므로, 배열 요소를 직접 변경하면 원본 배열도 변경됩니다.
  • 장점: 여러 값을 한 번에 전달하고 변경할 수 있습니다.
public class ArrayExample {
    public static void changeArray(int[] arr) {
        arr[0] = 100;
    }
}

List

  • 개념: List는 배열과 유사하지만, 동적 크기 조절이 가능합니다.
  • 장점: 배열보다 유연하게 데이터를 관리할 수 있습니다.
import java.util.ArrayList;
import java.util.List;

public class ListExample {
    public static void changeList(List<Integer> list) {
        list.set(0, 100);
    }
}

Builder 패턴

  • 개념: 객체를 생성할 때, 변경 가능한 객체를 이용하여 단계적으로 객체를 구성합니다.
  • 장점: 복잡한 객체 생성 과정을 간소화하고, 불변 객체를 생성할 수 있습니다.
public class BuilderPattern {
    public static class PersonBuilder {
        private String name;
        private int age;

        public PersonBuilder setName(String name) {
            this.name = name;
            return this;
        }

        pu   blic PersonBuilder setAge(int age) {
            this.age = age;
            return this;
        }

        public Person build() {
               return new Person(name, age);
        }
    }
}

선택 기준

  • 원본 객체 변경 여부: 원본 객체를 변경해야 하는 경우 객체 반환, 배열, List를 고려합니다.
  • 데이터 타입: 기본형 변수는 Wrapper 클래스를 사용하고, 복잡한 객체는 Builder 패턴을 고려합니다.
  • 유연성: List는 동적 크기 조절이 가능하여 유연하게 데이터를 관리할 수 있습니다.
  • 불변성: 불변 객체를 선호하는 경우 Builder 패턴을 사용합니다.
  • 객체 참조: 참조형 변수를 전달할 때는 주소값이 복사되므로, 함수 내에서 객체의 내용을 변경하면 원본 객체도 변경됩니다.

java methods parameter-passing

java methods parameter passing

Maven에서 종속성의 최신 버전을 사용하는 방법

1. pom. xml 파일에 latest 키워드 사용:위 코드는 Maven에게 spring-core 종속성의 최신 버전을 사용하도록 지시합니다. Maven은 사용 가능한 최신 안정적인 버전을 선택합니다.2. 범위 버전 사용:


Java에서 프라이빗 메서드, 필드 또는 내부 클래스를 포함하는 클래스를 테스트하는 방법

다음은 프라이빗 요소를 포함하는 클래스를 테스트하는 데 도움이 되는 몇 가지 전략입니다.1. 접근성 변경: 테스트 코드에서 프라이빗 요소에 접근할 수 있도록 임시적으로 접근성을 변경합니다.모듈 테스트: --module-path 옵션을 사용하여 JUnit 모듈 테스터에게 테스트 대상 모듈에 대한 읽기/쓰기 권한을 부여할 수 있습니다


자바 리플렉션이란 무엇이며 왜 유용한가요?

자바 리플렉션은 프로그램 실행 중에 클래스, 필드 및 메소드와 같은 런타임 정보에 액세스하고 조작할 수 있도록 하는 강력한 기능입니다. 컴파일 시점에 코드가 아닌 실행 시점에 클래스에 대한 정보를 활용할 수 있기 때문에 동적이라고 불립니다


Java HashMap과 Hashtable의 차이점: 자세한 설명

HashMap과 Hashtable은 Java에서 많이 사용되는 Map 인터페이스를 구현한 클래스로, 데이터를 key-value 쌍으로 저장하는 데 사용됩니다. 둘 다 해시 테이블 구조를 기반으로 하지만 몇 가지 중요한 차이점이 있습니다