자바의 자료형은 크게 기본 타입(primitive type)과 참조 타입(reference type)으로 나누어진다. 대표적으로 기본 타입은 char, int, float, double, boolean 등이 있고 참조 타입은 class, interface 등이 있다. 여기서 기본 타입(primitive type)을 객체로 다루기 위해서 사용하는 클래스들을 래퍼 클래스(wrapper class)라고 한다. 자바는 모든 기본 타입(primitive type)을 래퍼 클래스(wrapper class)로 만들 수 있다. 주의할 점으로는 래퍼 클래스(wrapper class)로 감싸고 있는 기본 타입 값은 외부에서 변경할 수 없다.
Integer num = new Integer(3);
num = 5;
System.out.println("num = " + num);
콘솔 창을 보면 5가 출력되어 num이 3에서 5로 값 자체가 바뀌는 것처럼 보인다. 하지만 원래 num이 3이라는 객체를 참조하다가 5라는 객체를 참조하도록 참조 객체가 바뀌는 것이다.
wrapper 클래스는 산술 연산을 위해 정의된 클래스가 아니다. 따라서 연산 과정에서 기본 타입과 래퍼 타입을 변환하는 과정이 필요한데 boxing과 unboxing이 여기서 사용된다.
Integer num = new Integer(10); // Integer 래퍼 클래스 num 에 10의 값을 저장
int n = num.intValue(); // 래퍼 클래스 num 의 값을 꺼내 가져온다.
JDK 1.5 부터는 boxing과 unboxing이 필요한 상황에 자바 컴파일러가 자동으로 처리해주기 시작했다. 이러한 자동화된 boxing과 unboxing을 auto boxing과 auto unboxing이라고 부른다. 기본타입 값을 직접 boxing, unboxing 하지 않아도 래퍼 클래스 변수에 대입만 하면 자동으로 boxing과 unboxing이 된다.
Integer num = 17; // new Integer() 생략
int n = num; // intValue() 생략
💡 기능적 편의성을 위하여 auto boxing, auto unboxing을 제공하지만, 다른 타입 간의 형 변환은 애플리케이션의 성능에 영향을 미치게 된다. 비록 사소한 차이 일지라도 애플리케이션의 성능 측면에서 봤을 때 꼭 필요한 상황이 아니라면 지양하는 것이 좋다.
직렬화 : 객체를 저장, 전송할 수 있는 특정 포맷 상태로 바꾸는 과정이다.
역직렬화 : 말 그대로 직렬화의 반대이다. 즉, 특정 포맷 상태의 데이터를 다시 객체로 변환하는 것을 뜻한다.
[Java] 직렬화(Serialization)와 역직렬화(Deserialization)란? transient 변수란?
자바 직렬화 : 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술, 바이트로 변환된 데이터를 다시 객체로 변환하는 기술(역직렬화)을 아울러서 이야기한다. 직렬화하고자 하는 객체에 Serializable를 상속받도록 하면 된다.
자바 직렬화를 사용하는 이유 : 자바 직렬화는 자바 시스템 간의 데이터 교환에 최적화되어 있다. 복잡한 데이터 구조의 클래스의 객체라도 직렬화 기본 조건만 지키면 큰 작업 없이 바로 직렬화를 가능하다. 보통 서블릿 세션, 캐시, 자바 RMI에서 사용된다.
💡 하지만 자바 직렬화는 보안과 유지보수등 단점이 많아서 되도록이면 사용하지 말고 Json 같은 다른 포맷을 사용하는것을 권장한다고 한다.
지역 변수 : 메서드 내에서 선언되며 메서드 내에서만 사용할 수 있는 변수다. 메서드가 실행될 때 메모리를 할당 받으며 메서드가 끝나면 소멸되어 사용할 수 없게 된다. stack 메모리 영역에 저장된다.
인스턴스 변수(멤버 변수) : 인스턴스 변수는 인스턴스가 생성될 때 생성된다. 그렇기 때문에 인스턴스 변수의 값을 읽어오거나 저장하려면 인스턴스를 먼저 생성해야한다. 인스턴스 별로 다른 값을 가질 수 있으므로, 각각의 인스턴스마다 고유의 값을 가져야할 때는 인스턴스 변수로 선언한다. heap 메모리 영역에 저장된다.
클래스 변수(static 변수) : static 변수는 프로그램 실행 시 생성되고 종료될 때 소멸된다. 따라서 프로그램이 실행되는 동안에는 값이 유지되어야 하는 경우에 사용된다. method 메모리 영역에 저장된다.
synchronized 키워드를 직접 사용해서 특정 메소드나 구간에 Lock을 걸어 스레드 간 상호 배제를 구현할 수 있다. 메서드에 직접 걸어줄 경우에는 해당 class 인스턴스에 대해 Lock이 걸리고 synchronized 블록을 이용할 경우에는 블록으로 감싸진 구간만 Lock이 걸린다.
한계
1. 자바의 Sychronized는 하나의 프로세스 안에서만 보장이 된다. 즉, 서버가 1대일때는 문제가 없지만 서버가 2대 이상일 경우 데이터에 대한 접근을 막을 수 없다. 서버가 여러대 일 경우, Synchronized 는 각 프로세스의 동시접근 제어만을 보장해주기 때문에 다른 서버에서 가변 공유데이터에 접근하는 것을 막을 수 가 없어, 업데이트 도중 값이 변경될 수 있는 문제점이 여전히 남아 있다.
참고로 자바에서 클라이언트 요청 하나가 스레드이다.
💡 대안으로 RDB 락을 사용하거나 redis 분산락을 사용한다.