-
[Java] 기본형 vs 참조형언어/Java 2024. 11. 5. 09:26
아래 내용은 위 링크에서 더 자세히 볼 수 있습니다.
자바에서 참조형을 제대로 이해하는 것은 정말 중요하다
기본형 vs 참조형 1
- 기본형
- 사용하는 값을 변수에 직접 넣을 수 있는 기본형
- 들어 있는 값을 그대로 계산에 사용할 수 있다.
- 참조형
- 데이터에 접근하기 위해 참조(주소)를 저장하는 데이터 타입
- 참조형은 들어있는 참조값을 그대로 사용할 수 없다. ex) 주소끼리 더하고 빼면 뭐하냐 이상한 메모리에 접근이나 하겠지..
- String도 클래스이다. 따라서 참조형이다. 그런데 기본형처럼 문자값을 바로 대입할 수 있다. 문자는 매우 자주 다루기 때문에 자바에서 특별 취급 받아버림
// Primitive Type int a = 10; int b = 20; int sum = a + b; sout(sum); // 30 // Reference Type Student student1 = new Student(); Student student2 = new Student(); sout(student1); // 0x001 sout(student2); // 0x002
기본형 vs 참조형 2
자바는 항상 변수의 값을 복사해서 대입한다.
package ref; public class VarChange1 { public static void main(String[] args) { int a = 10; int b = a; System.out.println("a :" + a); // 10 System.out.println("b :" + b); // 10 a = 20; System.out.println("a :" + a); // 20 System.out.println("b :" + b); // 10 b = 30; System.out.println("a :" + a); // 20 System.out.println("b :" + b); // 30 } }
package ref; public class VarChange2 { public static void main(String[] args) { Data dataA = new Data(); dataA.value = 10; Data dataB = dataA; System.out.println("dataA 참조값: " + dataA); // 주소 System.out.println("dataB 참조값: " + dataB); // 주소 System.out.println("dataA value: " + dataA.value); // 10 System.out.println("dataB value: " + dataB.value); // 10 // dataA change dataA.value = 20; System.out.println("변경 dataA.value = 20"); System.out.println("dataA.value: " + dataA.value); // 20 System.out.println("dataB.value: " + dataB.value); // 20 // dataB change dataB.value = 30; System.out.println("변경 dataB.value = 30"); System.out.println("dataA.value: " + dataA.value); // 30 System.out.println("dataB.value: " + dataB.value); // 30 } }
- dataB change에서 dataB =dataA의 주소를 가리킨다. 주소를 찾아가서 값을 바꿨으니가 dataA.value도 바뀌는 것이다.
기본형 vs 참조형3
자바는 항상 변수의 값을 복사해서 대입한다.
메서드 호출도 마찬가지이다.package ref; public class MethodChange2 { public static void main(String[] args) { Data dataA = new Data(); dataA.value = 10; System.out.println("메서드 호출 전 dataA.value : " + dataA.value); changeReference(dataA); System.out.println("메서드 호출 후 dataA.value : " + dataA.value); } public static void changeReference(Data dataX) { dataX.value = 20; } /* * 20으로 바뀔 거 같다. 그 이유는 * dataA의 주소가 0x001이면 * 메서드에 파라미터에 인자로 들어갈 때 주소값이 들어가는 것 0x001 * 따라서 0x001.value = 20; 으로 바꾸었으니 20이 될 것이다. * */ }
- C의 포인터 개념을 알고 있으면 떠올리기 쉬울 듯 하다.
- 참조값이 복사되어 전달된다. 0x001이 전달. 따라서 dataA와 dataX는 둘 다 같은 곳을 바라보고 있다.
메서드 객체 바꾸기
package ref; public class Method2 { public static void main(String[] args) { Student student1 = createStudent("학생1", 16, 90); Student student2 = createStudent("학생2", 18, 80); printStudent(student1); printStudent(student2); } static Student createStudent(String name, int age, int grade) { Student student = new Student(); // 0x001 student.name = name; student.age = age; student.grade = grade; return student; } public static void printStudent(Student student) { // 0x001 값을 넘겨서 가능하구나 !! System.out.println("name : " + student.name + ", age : " + student.age + ", grade: " + student.grade); } }
- createStudent 라는 메서드를 만들고 객체를 생성하는 부분도 이 메서드 안에 포함했다.
- 클래스 정보를 기반으로 새로운 객체를 생성했다.
- 궁금했던 점 : 새로운 객체를 사용할 때 객체는 고유한 메모리 주소를 가지는 가? 그렇다고 한다.
- 새로운 객체는 힙 영역에서 계속 생성된다고 한다. 사용하지 않으면 가비지 컬렉터가 알아서 해주는 데(묵시적) 만약 계속 참조되고 있다면, 힙 오버 플로우가 발생할 수도 있다고 한다. 사실상 런타임때 outOfMemoryError를 내기 때문에 비슷하지만, 약간 다른 느낌 넘어간다.
'언어 > Java' 카테고리의 다른 글
[Java] 객체 지향 프로그래밍 (4) 2024.11.06 [Java] 변수와 초기화, null, nullPointerException (0) 2024.11.05 [Java] 클래스, 객체(인스턴스) (5) 2024.11.04 [Java] 반환타입, 메서드 오버로딩 (0) 2024.10.30 [Java] 메서드 (feat. 인수 != 매개변수) (2) 2024.10.29 - 기본형