일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 백엔드
- 데이터 조회
- Java
- JavaScript
- 프론트엔드
- 웹개발
- Git
- 정보처리기사필기요약
- 백준
- 프로그래밍
- sql문
- 입출력
- html
- 메서드
- 정보처리기사
- mybatis
- 스프링
- BufferedReader
- 자바
- String클래스
- select문
- select
- Linux
- 자바스크립트
- github
- order by
- 알고리즘
- 개발자
- SQL
- MySQL
- 프로그래머스 sql 고득점 kit
- 리눅스
- 클래스
- 프로그래머스 SQL
- scanner
- where
- 형변환
- StringBuilder
- 예외처리
- DML
- Today
- Total
ToBe끝판왕
[ JAVA ] 불변 객체 ( 기본형과 참조형 ) 본문
■ java.lang 패키지 에 관하여 알아보자 !
• 자바 언어를 이루는 가장 기본이 되는 클래스들을 보관하는 패키지
• java.lang 패키지의 대표적인 클래스
- Object : 모든 자바 객체의 부모 클래스
- String : 문자열
- Integer, Long, Double : 래퍼타입 , 기본형 데이터 타입을 객체로 만든 것
기본형( Primitive Type) 와 참조형( Reference Type )
• 기본형
- 하나의 값을 여러 변수에서 절대로 공유하지 않음
• 참조형
- 하나의 객체를 통해 여러 변수에서 공유 가능
• 기본형( Primitive Type ) 예시
- b = a 에서 자바는 항상 값을 복사해서 대입한다.
- a 와 b 둘다 10이란 같은 숫자의 값을 가지지만, a가 가지는 10과 b가 가지는 10은 완전히 다른 10이다.
- 메모리상에도 a에 속하는 10과 b에 속하는 10이 각각 별도로 존재한다.
package lang.immutable.address;
public class PrimitiveMain {
public static void main(String[] args) {
// 기본형은 절대로 같은값을 공유하지 않는다.
int a = 10;
int b = a; // a -> b, 값 복사 후 대입
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println();
b = 20;
System.out.println("20 -> b");
System.out.println("a = " + a);
System.out.println("b = " + b);
}
}
// 실행 결과
a = 10
b = 10
20 -> b
a = 10
b = 20
• 참조형( Reference Type ) 의 예시
- Address b = a 코드에서 변수 a, b 둘다 서울이라는 주소를 가지게 된다.
- 이후, b의 주소를 부산으로 변경하는데 a의 주소도 함께 부산으로 변경이 된다. ( 문제점 )
- Address b = a 코드에서 a의 참조값을 복사하여 b에 전달하는데, a와 b가 같은 참조값을 통하여 같은 인스턴스를 참조하게 되었다.
( a와 b 는 같은 참조값으로 같은 인스턴스를 참조하기 때문에 같이 부산으로 변경이 되는 원인 --> 사이드 이펙트 발생 )
-
package lang.immutable.address;
public class Address {
private String value;
public Address(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "Address{" +
"value='" + value + '\'' +
'}';
}
}
package lang.immutable.address;
public class RefMain1_1 {
public static void main(String[] args) {
// 참조형 변수는 하나의 인스턴스를 공유할 수 있다.
Address a = new Address("서울");
Address b = a;
System.out.println("a = " + a);
System.out.println("b = " + b);
b.setValue("부산");
System.out.println("부산 -> b");
System.out.println("a = " + a);
System.out.println("b = " + b);
}
}
// 실행 결과
a = Address{value='서울'}
b = Address{value='서울'}
부산 -> b
a = Address{value='부산'}
b = Address{value='부산'}
불변객체( Immutable Object )
• 위와 같이, 여러 변수가 하나의 객체를 공유하는 것을 막을 방법이 없다.
• 참조값을 다른 변수에 대입하여 객체간의 공유가 일어나지만 자바 문법상 정상인 코드이다.
• 사이드 이펙트의 핵심은 공유 참조하는 인스턴스의 값을 변경하기 때문에 발생한다.
• 이를 해결 하기 위해 객체의 상태( 객체 내부의 값, 필드, 멤버변수 )가 변하지 않는 불변객체를 도입해야 한다.
• 불변객체(클래스) 예시
- 인스턴스 생성시 final 로 선언
- 생성자를 통해서만 값 설정 가능, 이후에는 값 변경 불가능
package lang.immutable.address;
public class ImmutableAddress {
// 내부값이 변경되면 안되므로 final로 선언
private final String value;
public ImmutableAddress(String value) {
this.value = value;
}
public String getValue() {
return value;
}
// 내부값 변경이 가능한 setter 는 존재 X
@Override
public String toString() {
return "Address{" +
"value='" + value + '\'' +
'}';
}
}
package lang.immutable.address;
public class RefMain2 {
public static void main(String[] args) {
ImmutableAddress a = new ImmutableAddress("서울");
ImmutableAddress b = a; // 참조값 대입을 막을 수 있는 방법 X ( 자바 문법상 문제 X )
System.out.println("a = " + a);
System.out.println("b = " + b);
// b.setValue("부산") 이 안됨 -> 불변객체 유추 , b의 값을 부산으로 변경해야함
b = new ImmutableAddress("부산");
System.out.println("부산 -> b");
System.out.println("a = " + a);
System.out.println("b = " + b);
}
}
// 실행 결과
a = Address{value='서울'}
b = Address{value='서울'}
부산 -> b
a = Address{value='서울'}
b = Address{value='부산'}
• 불변객체를 사용하지만 값을 변경하는 메서드가 필요한 경우
- 불변객체는 기존값은 변경하지 않은채, 계산 결과를 바탕으로 새로운 객체를 만들어서 반환
- 불변도 유지하며 새로운 결과 또한 만들 수 있다.
package lang.immutable.change;
public class ImmutableObj {
// 불변 객체 ( final 사용 ) , 절대 바뀌면 안된다.
private final int value;
public ImmutableObj(int value) {
this.value = value;
}
// 새로운 객체를 생성하여 반환한다.
public ImmutableObj add(int addValue) {
int result = value + addValue;
return new ImmutableObj(result);
}
public int getValue() {
return value;
}
}
package lang.immutable.change;
public class ImmutableMain1 {
public static void main(String[] args) {
ImmutableObj obj1 = new ImmutableObj(10);
ImmutableObj obj2 = obj1.add(20);
// 계산 이후에도 기존값과 신규값 모두 확인 가능
System.out.println("obj1 = " + obj1.getValue());
System.out.println("obj2 = " + obj2.getValue());
}
}
// 기존값이 변경해야 하는 메서드가 필요한 경우, 변경된 결과를 새로운 객체에 담아 반환
// 실행 결과
obj1 = 10
obj2 = 30
※ 참고사항
• 불변 객체에서 값을 변경하는 메서드의 경우, "with"으로 이름을 시작하게 하는 경우가 많다.
※ 해당 내용은 인프런 김영한 강사님의 "실전 자바 중급1" 인강의 참고자료와 예시들을 참고하였습니다
'■ 프로그래밍 SKILLS > JAVA' 카테고리의 다른 글
[ JAVA ] String 클래스 (2) (0) | 2024.08.19 |
---|---|
[ JAVA ] String 클래스 (1) (0) | 2024.08.13 |
[ JAVA ] Object 클래스 (0) | 2024.08.11 |
[ JAVA ] 예외처리를 위한 try-catch-finally 문 (0) | 2024.05.29 |
[ JAVA ] 문자열 한 글자씩 분리하기 (1) | 2024.05.15 |