Java에서는 어레이가 값으로 전달됩니까, 참조로 전달됩니까?
어레이는 Java에서 원시 유형은 아니지만 개체도 아니기 때문에 값으로 전달됩니까, 참조로 전달됩니까?어레이에 포함되는 항목(예: 참조 또는 원시 유형)에 따라 달라집니까?
Java의 모든 것은 값으로 전달됩니다.어레이(오브젝트 이외에는 아무것도 아님)의 경우 어레이 참조는 값으로 전달됩니다(오브젝트 참조가 값으로 전달되는 것과 같음).
배열을 다른 메서드에 전달하면 실제로 해당 배열에 대한 참조가 복사됩니다.
- 이 참조를 통해 어레이 내용이 변경되면 원래 어레이에 영향을 줍니다.
- 그러나 새 배열을 가리키도록 참조를 변경해도 원래 메서드의 기존 참조는 변경되지 않습니다.
이 투고를 참조해 주세요.Java는 "pass-by-reference"입니까, 아니면 "pass-by-value"입니까?
다음의 작업 예를 참조해 주세요.
public static void changeContent(int[] arr) {
// If we change the content of arr.
arr[0] = 10; // Will change the content of array in main()
}
public static void changeRef(int[] arr) {
// If we change the reference
arr = new int[2]; // Will not change the array in main()
arr[0] = 15;
}
public static void main(String[] args) {
int [] arr = new int[2];
arr[0] = 4;
arr[1] = 5;
changeContent(arr);
System.out.println(arr[0]); // Will print 10..
changeRef(arr);
System.out.println(arr[0]); // Will still print 10..
// Change the reference doesn't reflect change here..
}
당신의 질문은 잘못된 전제에 근거하고 있습니다.
어레이는 Java에서 원시 유형은 아니지만 개체도 아닙니다."
실제로 Java의 모든 어레이는 객체입니다1.모든 Java 어레이 유형에는java.lang.Object합니다.ObjectAPI.
...그러면 가치나 참조에 의해 전달되는 건가요?어레이에 포함되는 항목(예: 참조 또는 원시 유형)에 따라 달라집니까?
간단한 답변: 1) 값별로 전달, 2) 차이가 없습니다.
더 긴 답변:
모든 Java 객체와 마찬가지로 어레이는 값...으로 전달되지만 값은 어레이에 대한 참조입니다.따라서 호출된 메서드로 어레이의 셀에 무언가를 할당하면 발신자가 보는 것과 동일한 어레이 객체에 할당됩니다.
이것은 참조가 아닙니다.실제 pass-by-reference에는 변수의 주소를 전달하는 작업이 포함됩니다.실제 pass-by-reference를 사용하면 착신 메서드는 로컬 변수에 할당할 수 있습니다.이것에 의해, 발신자내의 변수가 갱신됩니다.
자바에서는 안 돼요.Java에서 호출된 메서드는 배열의 내용을 업데이트할 수 있으며 배열 참조 복사본을 업데이트할 수 있지만 호출자의 배열 참조를 유지하는 호출자 변수를 업데이트할 수 없습니다.그래서...자바가 제공하는 것은 패스 바이 레퍼런스가 아닙니다.
다음은 참조별과 값별의 차이를 설명하는 링크입니다.위의 설명을 이해하지 못하거나 용어에 동의하지 않으신다면 읽어보시기 바랍니다.
- http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm
- http://www.cs.fsu.edu/~myers/c++/notes/references.disples
관련 SO 질문:
이력 배경:
"pass-by-reference"라는 문구는 원래 "call-by-reference"로, FORTRAN (call-by-reference)의 인수 전달 시멘틱스를 ALGOL-60 (call-value 및 call-by-name)의 시멘틱스와 구별하기 위해 사용되었습니다.
값별 콜에서는 인수식이 값으로 평가되고 그 값이 착신 메서드에 복사됩니다.
참조별 호출에서는 인수식은 호출 메서드에 전달되는 "lvalue"(변수 또는 배열 요소의 주소)에 대해 부분적으로 평가된다.호출 메서드는 변수/요소를 직접 읽고 업데이트할 수 있습니다.
call-by-name에서는 실제 인수식은 여러 번 평가할 수 있는 호출 방식(!!)으로 전달됩니다.이는 구현이 복잡하여 이해하기 어려운 코드를 작성(남용)하는 데 사용될 수 있습니다.이름에 의한 콜은 Algol-60에서만 사용되었습니다(감사합니다).
갱신하다
실제로 Algol-60의 이름별 호출은 람다 식을 매개 변수로 전달하는 것과 유사합니다.문제는 이러한 정확하지 않은 lambda-표현식(실장 수준에서는 "Thunks"라고 불림)이 호출 절차/함수의 범위 내에 있는 변수 상태를 간접적으로 수정할 수 있다는 것입니다.그것이 그들을 이해하기 어렵게 만든 부분이다.(예를 들어 Jensen's Device의 Wikipedia 페이지를 참조하십시오).
1. 링크된 Q&A(자바의 Array 및 메모리에 저장되는 방법)에는 어레이가 객체가 아님을 명시하거나 암시하는 내용이 없습니다.
어레이는 사실상 객체이므로 참조가 전달됩니다(참조 자체는 값에 따라 전달되며 아직 혼란스럽습니까?).간단한 예:
// assuming you allocated the list
public void addItem(Integer[] list, int item) {
list[1] = item;
}
발신자 코드로부터 리스트의 변경이 표시됩니다.그러나 참조 자체는 값으로 전달되므로 변경할 수 없습니다.
// assuming you allocated the list
public void changeArray(Integer[] list) {
list = null;
}
null이 아닌 목록을 통과하면 메서드가 반환될 때까지 null이 되지 않습니다.
아니, 그건 틀렸어.어레이는 Java에서 특별한 객체입니다.즉, 참조 자체의 값이 아닌 참조의 값을 전달하는 다른 개체를 전달하는 것과 같습니다.즉, 호출된 루틴에서 배열 참조를 변경하면 호출 루틴에 반영되지 않습니다.
Java의 모든 것은 값에 의해 전달됩니다.
배열의 경우 참조가 새 참조로 복사되지만 Java의 모든 내용은 값으로 전달됩니다.
어레이에 대한 자세한 내용은http://http://docs.oracle.com/javase/specs/jls/se5.0/html/arrays.html#27803 를 참조해 주세요.이를 통해 Java 배열이 개체임을 알 수 있습니다.이러한 객체의 클래스는 10.8에 정의되어 있습니다.
언어 사양의 섹션 8.4.1(http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#40420)에서는 인수를 메서드에 전달하는 방법에 대해 설명합니다.Java 구문은 C 및 C++에서 파생되므로 동작은 비슷합니다.원시 유형은 C와 같이 값으로 전달됩니다.오브젝트가 전달되면 오브젝트 참조(포인터)가 값별로 전달되어 포인터를 값별로 전달하는 C 구문이 반영됩니다.4.3.1, http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.3 를 참조해 주세요.
실제로 이것은 메서드 내의 배열 내용을 변경하는 것이 호출 범위 내의 배열 객체에 반영되지만 메서드 내의 참조에 새로운 값을 재할당해도 호출 범위 내의 참조에는 영향을 주지 않는다는 것을 의미합니다.이것은 C 내의 구조체 또는 의 오브젝트에 대한 포인터가 기대하는 동작과 동일합니다.C++.
용어 혼동의 적어도 일부는 C가 일반적으로 사용되기 전의 고급 언어의 역사에서 비롯된다.이전에는 일반적이고 수준 높은 언어들이 주소별로 메모리를 직접 참조하는 것은 가능한 한 피해야 하는 것이었고 추상화 층을 제공하는 것이 언어의 역할로 여겨졌다.이것에 의해, 서브루틴으로부터 값을 반환하는 메카니즘을 명시적으로 서포트할 필요가 있었습니다(꼭 함수는 아닙니다).이 메커니즘은 'pass by reference'를 참조할 때 공식적으로 의미하는 것입니다.
C가 도입되었을 때는 프로시저 호출의 개념의 스트라이프다운이 포함되어 있었습니다.여기서 모든 인수는 입력 전용이며 발신자에게 반환되는 값은 함수 결과뿐입니다.그러나 참조 전달의 목적은 포인터의 명시적이고 광범위한 사용을 통해 달성될 수 있다.같은 목적을 가지고 있기 때문에 포인터를 어떤 값에 대한 참조로 건네는 관행을 흔히 참조에 의한 전달이라고 합니다.루틴의 시멘틱스가 참조에 의해 전달되는 파라미터를 호출하는 경우, C의 구문은 프로그래머가 포인터를 명시적으로 전달해야 합니다.값에 의한 포인터 전달은 C에서 pass by reference semantics를 구현하기 위한 설계 패턴입니다.
C에서 원시 포인터의 유일한 목적이 크래시 버그를 만드는 것처럼 보일 수 있기 때문에 후속 개발, 특히 Java는 파라미터를 전달하기 위한 안전한 수단으로 되돌리려고 노력해왔다.그러나 C의 우세로 인해 개발자들은 C 코딩의 익숙한 스타일을 모방해야 했다.그 결과 포인터와 유사하게 전달되지만 보다 안전한 참조를 위해 더 많은 보호와 함께 구현됩니다.대안으로 Ada와 같은 언어의 풍부한 구문을 들 수 있었지만, 이것은 환영받지 못하는 학습 곡선의 출현을 나타내어 Java의 채택 가능성을 줄였을 것이다.
즉, Java에서 어레이를 포함한 객체에 대한 매개 변수 전달 설계는 특히 참조에 의한 전달의 의미적 의도를 충족시키기 위한 것이지만, 참조를 값에 의해 전달한다는 구문과 함께 구현됩니다.
일종의 속임수 같은...참조조차 Java에서 값으로 전달되므로 참조 자체에 대한 변경은 호출된 함수 수준에서 범위가 지정됩니다.컴파일러 및/또는 JVM은 종종 값 유형을 참조로 변환합니다.
언급URL : https://stackoverflow.com/questions/12757841/are-arrays-passed-by-value-or-passed-by-reference-in-java
'source' 카테고리의 다른 글
| 계산된 속성 집합이 Vue에서 호출되지 않음 (0) | 2022.08.29 |
|---|---|
| Java에서 사용할 수 있는 변수를 Gradle에서 선언할 수 있습니까? (0) | 2022.08.29 |
| Function pointer를 사용하면 프로그램이 느려집니까? (0) | 2022.08.29 |
| VueJS 계산 데이터를 소품으로 전달하면 정의되지 않은 상태로 반환됨 (0) | 2022.08.29 |
| C의 풀 "for" 루프 구문은 무엇입니까? (0) | 2022.08.29 |