이 글을 읽기 전, 여러분의 경험과 이해를 바탕으로 자바 함수의 매개변수 전달 방식에 대해 먼저 생각해보고 선택해 보시기 바랍니다.
A.
B. 참조로 통과되었나요?
C. 일부는 값으로, 일부는 참조로?
정답은 아직 발표되지 않습니다. 모든 사람이 스스로 답을 찾을 수 있도록 간단한 예를 사용하겠습니다.
1. 먼저 유형 값을 정의
public static class Value { private String value = "value"; public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
2. 두 개 작성 newValue와 수정값이라는 두 가지 함수가 있습니다. newValue는 입력 매개변수를 새 객체로 가리키고, 수정값은 입력 매개변수의 setValue 메서드를 호출하여 객체의 값을 수정합니다.
public static void newValue(Value value) { value = new Value(); value.setValue("new value"); System.out.println("In newValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); } public static void modifyValue(Value value) { value.setValue("new value"); System.out.println("In modifyValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); }
3. 간단한 테스트 코드
public static void main(String[] args) { Value value1 = new Value(); System.out.println("Before modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue()); // 将value1指向新的Value对象 newValue(value1); System.out.println("After modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "\n"); Value value2 = new Value(); System.out.println("Before modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue()); // 使用object的set方法,修改对象的内部值 modifyValue(value2); System.out.println("After modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue()); }
4. 실행 결과 로그:
Before modify, HashCode = 12677476, value = value In newValue, HashCode = 33263331, value = new value After modify, HashCode = 12677476, value = value Before modify, HashCode = 6413875, value = value In modifyValue, HashCode = 6413875, value = new value After modify, HashCode = 6413875, value = new value
5. 🎜>위 코드는 매우 일반적인 프로그래밍 패턴입니다. 정의 | 저장 | 주변에서 값이나 객체를 가져오고, 객체를 매개변수로 메소드에 전달하고, 메소드에서 객체의 속성과 동작을 수정합니다. 하지만 newValue와 adjustValue 두 메소드의 수정 방법은 다릅니다. 메소드가 호출된 후 객체는 외부에서 매우 다르게 보입니다! 이 차이를 어떻게 이해해야 할까요? 먼저 값에 의한 전달과 참조에 의한 전달의 개념을 검토해 보겠습니다.
* 값에 의한 전달은 매개변수가 함수에 전달될 때 함수가 원래 값의 복사본을 수신한다는 의미입니다. 따라서 함수가 매개변수를 수정하면 복사본만 변경되고 원래 값은 변경되지 않습니다.
* 참조로 전달한다는 것은 인수가 함수에 전달될 때 함수가 값의 복사본이 아닌 원래 값의 메모리 주소를 받는 것을 의미합니다. 따라서 함수가 매개변수를 수정하면 매개변수의 원래 값(함수 블록 외부의 호출 코드에 있음)도 변경됩니다.
정답: A——Java 함수는 매개변수를 값으로 전달합니다!
로그 분석:
* 첫 번째 로그 출력에서는 newValue 메소드 내에서 value1 매개변수가 새 객체를 가리키도록 변경되고, 새 객체의 hashCode 및 값이 출력되지만, 점프한 후 newValue 메소드 도메인, 기본적으로 메소드의 value1에는 변경이 없습니다. 이는 값 전달의 정의 및 특성과 일치합니다. 참조로 전달되는 경우 value1은 newValue(Value value) 메소드를 호출한 후 변경되어야 합니다. .
* 두 번째 로그 출력에서 value2는 수정 값 메소드 내에서 setValue 작업을 수행합니다. hashCode는 변경되지 않지만 값은 수정 값 메소드 도메인을 떠난 후 기본 메소드에서 변경됩니다. C++를 사용해 본 사람들은 이 현상을 다음과 같이 쉽게 이해할 수 있습니다. 함수 매개변수를 참조로 전달합니다! 이는 C++의 참조로 전달하는 것과 매우 유사하기 때문입니다! 그러나 이것이 바로 오해에 빠질 가능성이 가장 높은 곳입니다!
두 로그의 서로 다른 현상 뒤에 있는 원리는 Java 언어가 매개변수를 값으로 전달하고 객체를 참조로 전달한다는 것입니다. Java에서 작동하는 객체는 실제로 작동 객체에 대한 참조이며 객체 자체는 "힙"에 저장됩니다. , 객체의 "참조"는 레지스터 또는 "스택"에 저장됩니다.
유사 코드는 newValue 메소드와 수정 값 메소드의 차이점을 설명합니다.
newValue{ Value_ref2 = value_ref1; // 按值传入引用value_ref1,得到value_ref1的副本 value_obj2 = new Value(); // value_obj2被创建、初始化在“堆“中 value_ref2 -> value_obj2; // value_ref2 指向value_obj2 value_ref2 ->value_obj2.setValue(“xxx”); // value_obj2 的value被修改 printValueObj2(); // 此处打印的是obj2的值 } modifyValue{ Value_ref2 = value_ref1; // 按值传入引用value_ref1,得到value_ref1的副本 value_ref2 ->value_obj1.setValue(“xxx”); // value_obj1 的value被修改 printValueObj1(); // 此处打印的是obj1的值 }
메서드 호출 시 매개변수를 제공해야 하며, 매개변수 목록에 지정된 순서대로 제공해야 합니다.
예를 들어 다음 메소드는 메시지를 n번 연속해서 인쇄합니다.
public static void nPrintln(String message, int n) { for (int i = 0; i < n; i++) System.out.println(message); }
다음 예는 값 전달의 효과를 보여줍니다.
이 프로그램은 두 변수를 교환하는 데 사용되는 메서드를 만듭니다.
public class TestPassByValue { public static void main(String[] args) { int num1 = 1; int num2 = 2; System.out.println("Before swap method, num1 is " + num1 + " and num2 is " + num2); // 调用swap方法 swap(num1, num2); System.out.println("After swap method, num1 is " + num1 + " and num2 is " + num2); } /** 交换两个变量的方法 */ public static void swap(int n1, int n2) { System.out.println("\tInside the swap method"); System.out.println("\t\tBefore swapping n1 is " + n1 + " n2 is " + n2); // 交换 n1 与 n2的值 int temp = n1; n1 = n2; n2 = temp; System.out.println("\t\tAfter swapping n1 is " + n1 + " n2 is " + n2); } }
Before swap method, num1 is 1 and num2 is 2 Inside the swap method Before swapping n1 is 1 n2 is 2 After swapping n1 is 2 n2 is 1 After swap method, num1 is 1 and num2 is 2