프로그래밍 언어에서는 메서드 간에 매개변수를 전달해야 하며, 이러한 전달 전략을 가치 추구 전략이라고 합니다.
프로그래밍에서 값을 찾는 데는 여러 가지 전략이 있는데, 가장 일반적인 전략은 값 전달과 참조 전달입니다.
값 전달과 참조 전달의 가장 큰 차이점은 전달 중에 복사본이 만들어지는지 여부입니다. 복사본이 전달되면 값 전달이고, 그렇지 않으면 참조 전달입니다.
Java 객체는 복사 프로세스가 있기 때문에 참조 관계를 복사하여 전달되므로 값 전달이지만, Java 객체의 경우 전달되는 것은 객체에 대한 참조라는 점을 제외하면 값 전달입니다.
확장된 지식
Java의 매개변수 전달 메커니즘을 이해해야 하는 경우 메모리 관리를 고려하여 더 자세히 알아볼 수 있습니다.
메모리 관리
첫 번째 선택은 객체 인스턴스를 생성해야 한다고 가정하고 새 객체를 생성하는 데 관련된 Java 메모리 영역을 파악하는 것입니다:
sqlUser user = new User() // User여기서는 예시용으로만 사용되는 사용자 정의 객체의 경우
Heap.
객체 인스턴스 데이터는 힙 메모리에 저장됩니다. new 키워드를 사용하여 객체를 생성하면 JVM은 힙 메모리에 객체 인스턴스용 메모리를 할당합니다.
힙은 모든 스레드가 공유하는 런타임 데이터 영역입니다. 힙에 할당된 메모리는 Java 쓰레기 수집기에 의해 관리되며 프로그래머가 수동으로 해제할 필요가 없습니다.
즉, 힙 공간은 실제로 힙 공간에서 이 주소에 대한 Java의 참조인 new User()의 내용을 보유합니다.
방법론 영역/메타 공간
클래스의 메타데이터는 메서드 영역에 저장됩니다. Java 8 이상에서는 기존의 영구 생성이 메타스페이스로 대체되었습니다.
메서드 영역도 마찬가지로 모든 스레드에서 공유됩니다.
User 클래스가 다음과 같이 정의되어 있다고 가정합니다:
arduinopublic class User { private String username; // 각 User 객체에 대해 힙에 저장된 인스턴스 변수 private String password; // 각 User 객체에 대해 힙에 저장된 인스턴스 변수 private static int userCount; // 메타공간에 저장된 정적 변수 // Constructor and methods... }
그런 다음 new User()에 의해 생성된 객체는 사용자 이름 및 비밀번호 변수의 값을 힙 메모리에 저장합니다. 그리고 정적 변수인 userCount는 다른 클래스 메타데이터와 함께 메타스페이스에 클래스의 일부로 저장됩니다. 사용자 객체를 여러 개 생성하더라도 userCount의 복사본은 하나만 존재합니다.
클래스 메타데이터
클래스 구조 정의: 여기에는 클래스의 이름, 직계 부모, 클래스가 구현하는 인터페이스, 클래스의 액세스 수준, 클래스가 클래스인지 인터페이스 또는 열거형인지 여부 등의 정보가 포함됩니다.
메소드 정보: 여기에는 클래스에 정의된 모든 메소드의 이름, 반환 유형, 매개변수 목록, 액세스 수정자, 예외 목록, 메소드의 바이트코드 등이 포함됩니다.
필드 정보: 여기에는 클래스에 정의된 모든 필드의 이름, 유형, 액세스 수정자 등이 포함됩니다.
상수 풀: 유형, 필드 및 메서드에 대한 다양한 리터럴과 기호 참조를 포함하는 런타임 상수 풀입니다.
호출 스택
각 스레드는 자체 호출 스택으로 실행되며, 각 메서드 호출은 호출 스택에 저장할 스택 프레임을 생성합니다.
스택 프레임에는 로컬 변수 테이블, 피연산자 스택, 동적 연결 정보 등이 포함됩니다. 로컬 변수 테이블에는 기본 유형의 변수와 객체 참조 변수가 저장됩니다.
여기서 중요한 부분은 먼저 메인 메서드를 실행하여 호출 스택에 스택 프레임을 생성한 다음 이 스택 프레임에 로컬 변수 User 사용자를 정의한 다음 new User()를 통해 힙 공간에 새로 생성된 객체의 인스턴스를 저장할 공간을 열어야 한다는 것을 이해해야 합니다. 데이터. 그런 다음 이 로컬 변수는 새로 생성된 객체가 저장된 힙 공간의 주소를 수신하는 데 사용됩니다.
다음은 생성된 인스턴스 객체 사용자를 다음과 같은 메서드에 전달할 때 디버그 모드에서 매개변수 전달 프로세스를 보여주는 예시입니다.
javascriptstatic void printName(User user){ user.getName(); }
여기에서 사용자 주소가 User@325임을 알 수 있습니다.
그런 다음 printName 메서드로 디버그합니다:
보시다시피 printName 메서드의 사용자 주소는 new User()의 주소와 동일하며, 이는 매개변수 전달 과정에서 사용자 값이 전달되었음을 의미합니다.
실제로 printName 메서드를 호출할 때 JVM은 스택 프레임에 로컬 변수 user를 생성하고 메인 메서드는 호출 시 자체 사용자 값을 printName 스택의 사용자에게 전달하는데, 이 과정은 복사본을 생성하는 것으로도 해석할 수 있습니다.
요약하자면
프로그래밍 언어 메서드 간에 매개변수를 전달하는 전략을 가치 추구 전략이라고 하며, 가치 추구 전략에는 여러 가지 종류가 있지만 가장 일반적인 것은 값 전달과 참조 전달입니다. 값 전달의 특별한 경우인 공유 객체 전달도 있습니다.
값 전달과 참조 전달의 가장 큰 차이점은 전달 중에 복사본이 만들어지는지 여부입니다. 복사본이 전달되면 값 전달이고, 그렇지 않으면 참조 전달입니다.
Java에서 매개변수 전달은 실제로 값 전달을 통해 이루어지지만, Java 객체의 경우 전달되는 것은 객체에 대한 참조라는 점을 제외하면 다릅니다.
Java의 가치 추구 전략은 공유 객체 전달이라고 결론을 내리는 것이 옳습니다.
하지만 모든 사람이 이해할 수 있도록 Java에서는 전달되는 값이 객체에 대한 참조라는 점을 제외하고는 값만 전달된다고 가정해 보겠습니다 . 이것도 잘못된 것은 아닙니다.





