간단하게 살펴보는 자바에서의 참조형식 데이터 입니다.
대표적인 데이터로는 배열(Array)과 컬렉션의 리스트(list)를 들 수 있습니다.
이러한 참조형식의 데이터는 아래와 같은 특징을 지니고 있습니다.
* 특징
- 참조형 변수 안에는 값들을 저장하고 있는 객체를 가르키는 주소를 가지고 있습니다.
- 힙 영역에 저장됩니다.
이러한 참조형식의 데이터를 사용할 때 우리는 복사(copy)에서 종종 실수를 하고는 합니다.
아래와 같은 코드를 살펴봅니다.
import java.util.Arrays;
import java.util.List;
public class ArrayAndList {
public static void main(String[] args) {
String array[] = {"data1", "data2", "data3"};
String copyArray[] = array;
copyArray[1] = "바꾸기";
System.out.println(Arrays.toString(copyArray));
System.out.println(Arrays.toString(array));
}
}
array라는 변수에 3개의 문자열을 대입하였고, copyArray라는 변수에는 array 변수를 대입 하였습니다.
그러면 여기서 하는 실수가 바로 그 다음줄에서 나오는 모습 입니다.
copyArray[1] = "바꾸기";
이러한 문제를 만나는 사람들은 아래와 같은 답변을 합니다.
"복사된 배열에 값을 넣었는데 기존 배열의 값이 바뀌었습니다."
자바에서의 참조형식의 데이터는 보관된 데이터의 주소값을 가지고 있습니다.
그러므로 위 코드에서도 배열값을 복사하려 한 다면 단순하게 대입연산자를 통하여 해주는 것이 아니라 반복문 또는 만들어진 클래스 등을 통하여 새로이 생성(new)하여 주어야 합니다.
위 코드를 간단하게 고쳐보면 아래처럼 clone 이라는 메소드를 통해 새로운 배열을 생성 해 낼 수 있습니다.
물론 1차원 이상의 배열(2차, 3차 등등)에서는 clone메소드가 원활하게 동작하지 않습니다. ^^;
import java.util.Arrays;
import java.util.List;
public class ArrayAndList {
public static void main(String[] args) {
String array[] = {"data1", "data2", "data3"};
//String copyArray[] = array;
String copyArray[] = array.clone(); //clone메소드를 사용 합니다.
copyArray[1] = "바꾸기";
System.out.println(Arrays.toString(copyArray));
System.out.println(Arrays.toString(array));
}
}
이를 실행하여 본 모습입니다.
예상한 바와 같이 각각의 변수가 서로 다른 곳의 데이터를 바라보기 때 문에 복사된 배열의 값이 바뀌더라도 기존 배열의 값은 영향을 받지 않습니다.
위 내용과 마찬가지로 컬렉션에서의 데이터도 비슷합니다.
1개의 변수를 생성한 뒤에 마찬가지로 간단하게 대입연산자를 통해 또다른 변수를 만들어 줍니다.
import java.util.Arrays;
import java.util.List;
public class ArrayAndList {
public static void main(String[] args) {
String array[] = {"data1", "data2", "data3"};
//String copyArray[] = array;
String copyArray[] = array.clone(); //clone메소드를 사용 합니다.
copyArray[1] = "바꾸기";
//System.out.println(Arrays.toString(copyArray));
//System.out.println(Arrays.toString(array));
//리스트를 한번 해 보면..
List<String> list = Arrays.asList("list data1", "list data2", "list data3");
List<String> copyList = list;
copyList.set(1, "리스트 데이터 바꾸기"); //복사된 곳 데이터 바꾸기!
System.out.println(list);
System.out.println(copyList);
}
}
list 변수의 내용을 간단하게 copyList 라는 변수에 대입하였습니다.
두개의 변수는 같은 공간의 데이터를 바라보기 때문에 어느 한쪽이 변화되면 다른 한쪽도 영향을 받습니다.
그러므로 위 코드도 list와 copyList의 데이터가 서로 변한 상태로 나타나게 됩니다.
이러한 형상을 방지하기 위해서는 새롭게(new) 만들어 주도록 코드를 수정해야 합니다.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayAndList {
public static void main(String[] args) {
String array[] = {"data1", "data2", "data3"};
//String copyArray[] = array;
String copyArray[] = array.clone(); //clone메소드를 사용 합니다.
copyArray[1] = "바꾸기";
//System.out.println(Arrays.toString(copyArray));
//System.out.println(Arrays.toString(array));
//리스트를 한번 해 보면..
List<String> list = Arrays.asList("list data1", "list data2", "list data3");
//List<String> copyList = list;
List<String> copyList = new ArrayList<>(list); //new를 통한 새로운 할당
copyList.set(1, "리스트 데이터 바꾸기");
System.out.println(list);
System.out.println(copyList);
}
}
ArrayList를 새로이 생성(new) 해 줌으로써 간단하게 해결 하였습니다.
자바(Java)에서의 참조형 데이터는 이처럼 서로 같은 공간을 바라보기 때 문에 항상 유의하여야 합니다.
대입 연산자로 내가 새로이 만들었다고 착각하는 순간 원래의 데이터가 바꾸어지기 때문 입니다.
이상으로 간단하게 살펴본 자바(Java)에서의 참조형 데이터에 관한 내용이였습니다.
궁금한점 또는 틀린 부분은 언제든 연락주세요!👻
'Java(자바) > Java 기본' 카테고리의 다른 글
Mybatis jdbctype(마이바티스 Jdbctype) (0) | 2022.07.18 |
---|---|
재미있고 어려운 Java의 람다(lambda) (0) | 2022.04.07 |
자바로 살펴본 재귀 함수의 동작 방법 - 2 (Java Recursive method with 순열) (2) | 2021.07.28 |
자바로 살펴본 재귀 함수의 동작 방법 - 1 (Java Recursive method) (2) | 2021.07.27 |
자바 날짜 값 밀리세컨드 값으로 변환(Java date milliseconds) (0) | 2021.07.06 |
댓글