Java는 참조로 전달합니까 아니면 값으로 전달합니까?

많은 프로그래밍 언어에서는 참조 또는 값으로 매개 변수 전달할 수 있습니다. Java에서는 매개 변수 를 value 로만 전달할 수 있습니다 . 이것은 약간의 제한을 부과하고 또한 질문을 제기합니다. 예를 들어, 메소드에서 매개 변수 값이 변경되면 메소드 실행 후 값은 어떻게됩니까? Java가 메모리 힙에서 객체 값을 어떻게 관리하는지 궁금 할 수도 있습니다. 이 Java Challenger 는 Java의 객체 참조에 대한 이러한 질문과 기타 일반적인 질문을 해결하는 데 도움 이 됩니다.

소스 코드 받기

이 Java Challenger에 대한 코드를 가져옵니다. 예제를 따르는 동안 자체 테스트를 실행할 수 있습니다.

개체 참조는 값으로 전달됩니다.

Java의 모든 개체 참조는 값으로 전달됩니다. 이것은 값의 사본이 메소드에 전달됨을 의미합니다. 그러나 비결은 값의 복사본을 전달하면 객체의 실제 값도 변경된다는 것입니다. 이유를 이해하려면 다음 예제로 시작하십시오.

 public class ObjectReferenceExample { public static void main(String... doYourBest) { Simpson simpson = new Simpson(); transformIntoHomer(simpson); System.out.println(simpson.name); } static void transformIntoHomer(Simpson simpson) { simpson.name = "Homer"; } } class Simpson { String name; } 

메소드가 실행 된 simpson.name후의 의지는 무엇이라고 생각 transformIntoHomer하십니까?

이 경우 호머입니다! 그 이유는 Java 개체 변수가 메모리 힙의 실제 개체를 가리키는 단순히 참조이기 때문입니다. 따라서 Java가 매개 변수를 값으로 메소드에 전달하더라도 변수가 객체 참조를 가리키면 실제 객체도 변경됩니다.

이것이 어떻게 작동하는지 아직 명확하지 않은 경우 아래 그림을 살펴보십시오.

라파엘 치넬 라토 델 네로

기본 유형이 값으로 전달됩니까?

객체 유형과 마찬가지로 기본 유형도 값으로 전달됩니다. 다음 코드 예제에서 기본 유형에 어떤 일이 발생하는지 추론 할 수 있습니까?

 public class PrimitiveByValueExample { public static void main(String... primitiveByValue) { int homerAge = 30; changeHomerAge(homerAge); System.out.println(homerAge); } static void changeHomerAge(int homerAge) { homerAge = 35; } } 

값이 30으로 변경 될 것이라고 결정했다면 정확합니다. (다시) Java가 값으로 개체 매개 변수를 전달하기 때문에 30입니다. 숫자 30은 실제 값이 아니라 값의 복사본 일뿐입니다. 기본 유형은 스택 메모리에 할당되므로 로컬 값만 변경됩니다. 이 경우 개체 참조가 없습니다.

불변 객체 참조 전달

불변 String객체로 동일한 테스트를 수행하면 어떨까요?

JDK에는 많은 불변 클래스가 포함되어 있습니다. 예 래퍼 유형을 포함 Integer, Double, Float, Long, Boolean, BigDecimal, 물론 매우 잘 알려진 String클래스입니다.

다음 예에서 String.

 public class StringValueChange { public static void main(String... doYourBest) { String name = ""; changeToHomer(name); System.out.println(name); } static void changeToHomer(String name) { name = "Homer"; } } 

출력이 어떻게 될 것이라고 생각하십니까? ""를 맞히 셨다면 축하드립니다! 이는 String객체가 변경 불가능 하기 때문에 발생합니다. 즉 , 내부의 필드 String가 최종이며 변경할 수 없음 을 의미합니다 .

String클래스를 불변으로 만들면 Java에서 가장 많이 사용되는 객체 중 하나를 더 잘 제어 할 수 있습니다. a의 값 String이 변경되면 많은 버그가 발생합니다. 또한 String클래스 의 속성을 변경하지 않습니다 . 대신, 우리는 단순히 새로운 String가치를 할당하는 것입니다. 이 경우, 「홈런」값이 전달 될 name으로 changeToHomer하는 방법. String"호머"이 같은 쓰레기가 곧으로 수집 될 자격이 될 것입니다 changeToHomer방법은 실행을 완료합니다. 개체를 변경할 수 없더라도 지역 변수는 변경됩니다.

문자열 및 기타

Java의 String클래스 등에 대해 자세히 알아보기 : Java Challengers 시리즈에서 Rafael의 모든 게시물을 참조하십시오.

변경 가능한 객체 참조 전달

와 달리 StringJDK의 대부분의 객체는 StringBuilder클래스 처럼 변경 가능합니다 . 아래 예는 이전 예와 유사하지만 다음과 같은 기능 StringBuilder이 아닙니다 String.

 static class MutableObjectReference { public static void main(String... mutableObjectExample) { StringBuilder name = new StringBuilder("Homer "); addSureName(name); System.out.println(name); } static void addSureName(StringBuilder name) { name.append("Simpson"); } } 

이 예제의 결과를 추론 할 수 있습니까? 이 경우 변경 가능한 객체로 작업하기 때문에 출력은 "Homer Simpson"이됩니다. Java의 다른 변경 가능한 객체에서 동일한 동작을 기대할 수 있습니다.

이미 Java 변수가 값으로 전달된다는 것을 배웠습니다. 즉, 값의 복사본이 전달됩니다. 복사 된 값 이 Java 메모리 힙 의 실제 객체 를 가리킴을 기억하십시오. 값으로 전달하면 여전히 실제 객체의 값이 변경됩니다.

개체 참조 도전을 받아보세요!

이 Java Challenger에서는 객체 참조에 대해 배운 내용을 테스트합니다. 아래 코드 예제에서는 변경 불가능한 클래스 String와 변경 가능한 StringBuilder클래스 를 볼 수 있습니다 . 각각은 매개 변수로 메소드에 전달됩니다. Java는 값에 의해서만 전달된다는 것을 알면이 클래스의 기본 메소드가 실행되면 출력이 무엇이라고 생각합니까?

 public class DragonWarriorReferenceChallenger { public static void main(String... doYourBest) { StringBuilder warriorProfession = new StringBuilder("Dragon "); String warriorWeapon = "Sword "; changeWarriorClass(warriorProfession, warriorWeapon); System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon); } static void changeWarriorClass(StringBuilder warriorProfession, String weapon) { warriorProfession.append("Knight"); weapon = "Dragon " + weapon; weapon = null; warriorProfession = null; } } 

옵션은 다음과 같습니다.이 문서의 끝에서 정답을 확인하십시오.

A : 전사 = null 무기 = null

B : 전사 = 드래곤 무기 = 드래곤

C : 전사 = 드래곤 나이트 무기 = 드래곤 소드

D : 전사 = 드래곤 나이트 무기 = 검

방금 무슨 일이 있었나요?

위의 예에서 첫 번째 매개 warriorProfession변수는 가변 객체 인 변수입니다. 두 번째 매개 변수 인 weapon은 불변입니다 String.

 static void changeWarriorClass(StringBuilder warriorProfession, String weapon) { ... } 

이제이 메서드 내에서 무슨 일이 일어나고 있는지 분석해 보겠습니다. 이 메서드의 첫 번째 줄 Knight에서 warriorProfession변수에 값을 추가합니다 . 그것은 warriorProfession변경 가능한 객체라는 것을 기억하십시오 . 따라서 실제 오브젝트가 변경되고 그 값은 "드래곤 나이트"가됩니다.

 warriorProfession.append("Knight"); 

두 번째 명령어에서는 변경 불가능한 로컬 String변수가 "Dragon Sword"로 변경됩니다. 그러나 실제 개체는 변경되지 않고 String해당 속성이 최종 이므로 변경되지 않습니다 .

 weapon = "Dragon " + weapon; 

마지막으로 null여기 변수에 전달 하지만 객체에는 전달 하지 않습니다. 객체는 여전히 외부에서 액세스 할 수있는 한 동일하게 유지됩니다 (이 경우 main 메서드를 통해). 그리고 지역 변수는 null이지만 객체에는 아무 일도 일어나지 않습니다.

 weapon = null; warriorProfession = null; 

이 모든 것으로부터 우리는 변경 가능 StringBuilder및 불변 의 최종 값 String이 다음 과 같을 것이라는 결론을 내릴 수 있습니다.

 System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon); 

changeWarriorClass메서드 에서 변경된 유일한 값은 변경 warriorProfession가능한 StringBuilder객체 이기 때문에 입니다. 참고 warriorWeapon는 불변이기 때문에 변경하지 않은 String객체입니다.

Challenger 코드의 올바른 출력은 다음과 같습니다.

D : 전사 = 드래곤 나이트 무기 = 검.

비디오 도전! 자바에서 객체 참조 디버깅

디버깅은 프로그래밍 개념을 완전히 흡수하는 동시에 코드를 개선하는 가장 쉬운 방법 중 하나입니다. 이 비디오에서는 Java에서 객체 참조를 디버깅하고 설명하는 동안 따라갈 수 있습니다.

객체 참조의 일반적인 실수

  • 참조로 변경할 수없는 값을 변경하려고합니다.
  • 참조로 기본 변수를 변경하려고합니다.
  • Expecting the real object won't change when you change a mutable object parameter in a method.

What to remember about object references

  • Java always passes parameter variables by value.
  • Object variables in Java always point to the real object in the memory heap.
  • A mutable object’s value can be changed when it is passed to a method.
  • An immutable object’s value cannot be changed, even if it is passed a new value.
  • “Passing by value” refers to passing a copy of the value.
  • “Passing by reference” refers to passing the real reference of the variable in memory.

Learn more about Java

  • Get more quick code tips: Read all of Rafael's posts in the JavaWorld Java Challengers series.
  • Learn more about mutable and immutable Java objects (such as String and StringBuffer) and how to use them in your code.
  • Java의 기본 유형이 논란의 여지가 있다는 사실에 놀랄 수도 있습니다. 이 기능에서 John I. Moore는이를 유지하고 잘 사용하는 방법을 배우도록합니다.
  • Java Dev Gym에서 Java 프로그래밍 기술을 계속 구축하십시오.
  • Java 상속 디버깅이 마음에 들면 Rafael의 Java Challenges 비디오 재생 목록에서 더 많은 비디오를 확인하십시오 (이 시리즈의 비디오는 JavaWorld와 관련이 없음).
  • 스트레스없는 프로젝트를 진행하고 버그없는 코드를 작성하고 싶으십니까? NoBugsProject로 이동하여 NoBugsProject로 이동하여 No Bugs, No Stress-Create Life-Changing Software Without Destroying Your Life .

이 이야기는 "Java가 참조로 전달됩니까 아니면 값으로 전달됩니까?" 원래 JavaWorld에 의해 게시되었습니다.