[Java 자바] 변수, 자료형(원시형, 참조형), 메모리구조, 형변환
// 자바 변수 기본 규칙
// 1. 1개의 변수에는 1개의 값만 할당 가능
// 2. 변수에 저장된 값은 재할당으로 변경 가능
// 3. 값의 형태에 맞는 자료형을 사용
// 4. 변수명은 소문자로 시작(대문자 시작은 실행은 되지만 자제, 숫자 시작은 실행 안됨)
// 5. 자바 예약어 (이미 자바 자체에서 사용하고 있는 키워드는 변수명으로 사용 불가 String, int 등)
// 6. 자료형(data type)은 크게 두가지로 구분
- 원시형(primitive type) : 메모리 스택 영역에 실제 값을 저장한다.
- 참조형(reference type) : 메모리 스택 영역에는 객체의 주소를 저장하고 힙 영역에 실제 값을 저장한다.
// main 함수는 최초 진입점
public static void main(String[] args) {
//정수
int num = 1;
// 소수
double width = 12.34;
//문자열
String content = "Hello World";
// 시스템 출력 console.log 같은
System.out.println(content);
}
}
// 원시형 Primitive Type
// 1. 정수형 4가지 (표현 범위에 따라 구분)
// 1) byte (1byte = 8bits) 2^8 2의 8승만큼 범위를 다룸 (-128 ~ 127)
// 2) short (2bytes = 16bits) 2^16 2의 16승만큼 범위를 다룸 (-32,768 ~ 32,767)
// 3) int (4bytes = 32bits) 2^32 (-2^31 ~ 2^31 -1)
// 4) long (8bytes = 64bits) 2^64 (-2^63 ~ 2^63 -1)
// 2. 실수형
// 1) double (8bytes) = 소수점 15자리까지 다룸
// 2) float (4bytes) = 소수점 7자리까지 다룸
// 3. 문자형 (문자 1개만 다루는 것으로 문자'열'과 다름)
// 아스키코드, 유니코드 다 다룸
// 1) char (2bytes) 캐릭터
// 4. 논리형
// 1) boolean (1bytes)
public static void main(String[] args) {
// 원시형 Primitive Type
// 1. 정수형 4가지 (표현 범위에 따라 구분)
// 1) byte (1byte = 8bits) 2^8 2의 8승만큼 범위를 다룸 (-128 ~ 127)
// 2) short (2bytes = 16bits) 2^16 2의 16승만큼 범위를 다룸 (-32,768 ~ 32,767)
// 3) int (4bytes = 32bits) 2^32 (-2^31 ~ 2^31 -1)
// 4) long (8bytes = 64bits) 2^64 (-2^63 ~ 2^63 -1)
// 2. 실수형
// 1) double (8bytes) = 소수점 15자리까지 다룸
// 2) float (4bytes) = 소수점 7자리까지 다룸
float a = 9.22f; //float 은 값맨 뒤에 f 붙여야 함
// 3. 문자형 (문자 1개만 다루는 것으로 문자'열'과 다름)
// 아스키코드, 유니코드 다 다룸
// 1) char (2bytes) 캐릭터
char char1 = 'a'; // "" 쌍따옴표로는 안되네
char char2 = 97; // 아스키코드로 변환되어 나옴
char char3 = 0x61; // 유니코드로 변환되어 나옴
System.out.println(char1); // a
System.out.println(char2); // a
System.out.println(char3); // a
// 4. 논리형
// 1) boolean (1bytes)
boolean bool1 = true;
boolean bool2 = (1 < 0);
System.out.println(bool2); // false
}
}
// 참조형 Reference Type
원시형을 제외한 모든 데이터 타입을 참조형으로 보면 된다.
- 배열, 열거, 클래스, 인터페이스 등이 있다.
- 참조형의 실제 값은 heap 영역에 저장되고 stack 에는 heap의 주소값만 저장
public static void main(String[] args) {
// 참조형 예시
class Person {
final String name;
final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// new 는 객체를 생성하는 연산자
Person a = new Person("kim", 23);
Person b = new Person("Park", 30);
System.out.println(a); // ReferenceType$1Person@4eec7777 주소값을 반환
System.out.println(b); // ReferenceType$1Person@3b07d329 주소값을 반환
}
}
// 자바 메모리 구조
힙 heap 영역
new를 통해 생성된 모든 인스턴스가 저장되는 영역.
*인스턴스는 결국 참조형(reference type) 데이터 타입임을 의미
1)참조형으로 선언된 변수의 값은 heap 메모리 공간에 할당 (stack 영역에는 heap 주소가 할당)
2)heap 영역의 메모리는 가비지 컬렉터(Garbage Collector)를 통해 관리되며, 참조되지 않는 경우에는 해당 공간에 할당된 메모리가 해제된다. (때문에 개발자는 메모리 관리를 신경쓸 필요가 없다.)
스태틱 static 영역
전역변수가 저장되는 영역.
1)전역변수와 static이 붙은 클래스 메서드의 경우에 static 영역에 할당
2)프로그램의 시작부터 종료까지 메모리에 유지되며, 프로그램이 종료되는 때에 메모리에서 해제
3)static 메모리가 차지하는 공간은 프로그램 로드할 때 결정되기 때문에, 프로그램 컴파일 시간에 영향
4)static으로 선언된 경우 프로그램 전체에서 공유 (import 한 패키지 파일들도 static 영역에 저장)
스택 stack 영역 (call stack & execution stack)
지역변수와 일반 메소드가 저장되는 영역.
1)원시형의 경우 값 자체가 stack 영역에 할당
2)참조형 타입의 값을 지역 변수에 할당하면 stack 영역에는 heap의 주소값, heap 영역에는 실제값이 저장
3)메소드의 경우는 메소드가 호출될 때 메모리에 할당되고, 해당 메서드가 종료되면 메모리에서 해제
4)stack 영역은 LIFO(=Last In First Out) 구조
// 상수 (constants, final variables 라고도 함)
// 1) 한 번 값이 할당되면 재할당이 불가
// 2) 전체를 대문자로 표기, 단어간 구분은 _ 로 구분
// 3) 선언 키워드는 final ( final int a = 10; )
// 형변환
// byte < short < int < long <<< float < double
// 범위가 작은 것은 큰 것으로 변환될 수 있으나(자동 형변환) 반대는 안됨
// 서로 다른 형끼리 계산할 때 더 큰 범위로 강제 형변환 해야 데이터 손실이 없다.
public static void main(String[] args) {
// 형변환
// byte < short < int < long <<< float < double
// 범위가 작은 것은 큰 것으로 변환될 수 있으나(자동 형변환) 반대는 안됨
// int a = 128;
// short b = a; // 에러
// 강제 형변환 (또는 명시적 형변환)
int a = 128;
short b = (short) a;
byte c = (byte) a; // byte는 -128 ~ 127 까지 다룸
System.out.println(a); // 128
System.out.println(b); // 128
System.out.println(c); // -128 // 127까지 다 채우고 한바퀴 돌아서 맨 처음인 -128로 돌아옴
int m = 80;
double n = m;
System.out.println(m); // 80
System.out.println(n); // 80.0 실수로 형변환
double q = 10.1234567890012345;
float w = (float) q;
System.out.println(q); // 10.123456789001235
System.out.println(w); // 10.123457 출력 가능한 범위까지 짤림
int e = 10;
short f = 20;
// 더 큰 범위로 강제 형변환 해야 데이터 손실이 없다.
short g = (short) (e + f);
int t = (int) (e+f);
System.out.println(g); // 30
System.out.println(t); // 30
}
}