데이터 타입 전 메모리에 대해서
data의 종류는 크게 문자와 숫자, 숫자는 정수와 실수로 나눌 수 있다.
이러한 값의 타입에 따라 저장될 공간의 크기와 저장 형식을 정의한 것이 자료형, data type 이다.
논리형, 문자형, 정수형, 실수형 계산을 위한 실제 값을 저장한다.
논리형: boolean
true와 false 중에 하나를 값으로 가지며 조건식과 논리적 계산에 사용된다.
문자형: char
문자를 저장하는데 사용되며 변수 당 하나의 문자만 저장할 수 있다.
정수형: byte, short, int, long
정수 값을 저장하는데 사용된다.
byte는 이진 데이터를 다루는데 주로 사용, short는 C언어와 호환을 위해서 추가되었다.
실수형: float, double
실수를 저장하는데 사용된다.
boolean을 제외한 나머지 7개 기본형은 서로 연산과 변환이 가능하다.
변수마다 사용할 수 있는 값의 범위가 있다. 이 범위를 초과하게 되면 오버플로우(overflow)현상이 발생한다.
실수형의 정밀도
실수형은 정수형과 저장 방식이 다르기에 같은 크기라도 훨씬 큰 값을 표현할 수는 있지만,
오차가 발생할 수 있다. 그래서 정밀도(precision)가 중요한데, 정밀도가 높을수록 오차의 범위가 줄어든다.
참조형 타입은 위의 기본형 타입을 뺀 모든 형태(type)를 참조형 타입으로 볼 수 있다.
배열 (array[]), 열거 (enum), 클래스 (class), 인터페이스 (interface) 모두 참조형이라고 한다.
String name = "홍길동";
String[] hobby = new String() {"독서", "게임", "등산"};
Date Date = new Date();
리터럴은 데이터 그 자체를 뜻한다. 변수에 넣는 변하지 않는 데이터를 의미
int a = 1;
a라는 변수에 1이라는 값을 직접적으로 초기화 시켰다.
변하지 않는 고정적인 값을 리터럴이라고 한다.
long e = 21L;
정수 리터럴은 int형으로 컴파일 되며, long 타입 리터럴은 숫자 뒤에 L 또는 l을 붙여 표시한다.
int a = 10;
int b = 10;
10이라는 값을 Heap 메모리 영역 안에 있는 Constant Pool이라는 메모리 영역에 할당한다.
똑같은 값의 변수가 2개이지만 자바는 똑같은 값을 가진 변수를 호출 했을 때 전에 할당했던 메모리 주소를 넘겨준다.
a==b가 true가 나오는 이유도 a와 b가 똑같은 메모리 주소를 가르키고 있기 때문이다.
==은 메모리 주소를 비교합니다.
Constant Pool
Integer, String 같은 래퍼런스 타입의 데이터 값 또는, 메소드 호출 Class 호출 등을 저장하는 JVM의 메모리 공간 중 하나이다.
소수점 형태나 지수 형태로 표현한 값을 의미한다.
실수 타입 리터럴은 float, double 타입으로 컴파일 된다.
float h = 0.1234f;
float double = .1234D;
숫자 뒤에 f나 d를 명시적으로 붙이기도한다.
float 같은 경우에는 f를 꼭 붙여줘야하며, double는 생략 가능하다
문자 리터럴은 단일 인용부호('')로 문자를 표현한다.
char a = 'a';
char b = '한';
char c = \uae00;
유니코드나 직접 입력이 불가능한 문자들에 대해서는 역슬래쉬()를 이용하여 표시할 수 있다.
문자열 리터럴은 기본타입이 아니며, 이중 인용 부호("")로 지정하여 사용한다.
class Test {
public static void main(String[] args) {
String s1 = "str";
String s2 = "str";
System.out.println(System.identityHashCode(s1)); // 1134712904
System.out.println(System.identityHashcode(s2)); // 1134712904
}
}
변수를 선언하는 것은 미리 자원을 확보하는 동시에 사용한다는 의미를 가지고 있기 때문에 변수를 선언하지 않는다면 프로그램은 값(데이터)을 담아둘 공간이 없어 값을 사용할 수 없다.
public class Test {
// 필드, 멤버변수, 전역변수
char ch;
double var1;
String str = "";
public static void main(String[] args) {
//지역변수
int a; //int 타입의 변수 a 선언
a = 10; //변수 a에 10의 정수값으로 초기화
int b = 'b'; //변수 b를 선언하면서 'b'의 값을 저장
int c; //int 타입의 변수 c 선언
c = a; //변수 c에 변수 a의 값을 저장
}
}
변수를 선언하고 바로 뒤에 '=' 대입 연산자를 사용해 변수에 데이터를 집어넣는 걸 명시적 초기화라고 한다.
public class Test{
//필드, 전역(멤버) 변수
int a = 1000;
}
전역변수에서는 선언을 하자마자 0으로 초기화
지역 변수는 아무것도 들어가 있지 않는다
public class Test{
//필드, 전역(멤버) 변수
int a; //a=>0
double b; //b=>0.0
void test(){
//지역 변수
int a; //초기화X
double b; //초기화X
}
}
일반적인 초기화 블록(인스턴스 초기화 블럭) - 인스턴스 변수의 복잡한 초기화에 사용된다. 모든 생성자가 공통으로 수행해야 하는 로직이 있을 때 사용.
Class가 new 를 통해 인스턴스를 생성하는 순간 초기화가 진행
정적 초기화 블록(클래스 초기화 블럭) - 클래스 변수의 복잡한 초기화에 사용된다. 블럭 내에서는 로직도 추가할 수 있기에 명시적 초기화만으로 부족할 때 사용
JVM이 클래스로더로 로딩 시점에 초기화 진행
class test{
int hi = 3;
static int hello = 10;
//인스턴스 초기화 블럭
{
hi = 5;
}
//클래스 초기화 블럭
static {
hello = 20;
}
}
스코프 (영역)
변수에 접근하거나 접근할 수 있는 유효 범위/영역
변수가 선언된 블록내에서만 엑세스 할 수 있다.
블록은 왼쪽 중괄호 {
로 시작하고 오른쪽 }
로 끝난다.
변수의 라이프타임 (LifeTime)
변수가 메모리에서 살아있는 기간
클래스 내부와 모든 메소드 및 블록 외부에서 선언된 변수
스코프 - 정적 메서드를 제외한 클래스 전체
라이프타임 - 객체가 메모리에 남아있을 때까지
클래스 내부, 모든 블록 외부에서 선언되고 static으로 표시된 변수
스코프 - 클래스 전체
라이프타임 - 프로그램이 끝날때까지 또는 클래스가 메모리에 로드 되는 동안
인스턴스 및 클래스 변수가 아닌 모든 변수
스코프 - 선언된 블록 내에 있음
라이프타임 - 컨트롤이 선언 된 블록을 떠날때까지
연산을 수행하는 코드에서는 같은 타입끼리만 가능하다.
연산을 수행하기 전에 같은 타입으로 만드는 것을 타입변환이라고한다.
자바는 boolean을 제외한 나머지 기본 타입 간의 타입 변환을 할 수 있다.
프로모션(자동/묵시적 형변환) - 작은 데이터 타입에서 큰 데이터 타입으로 형 변환
캐스팅(명시적 형 변환) - 큰 데이터 타입에서 작은 데이터 타입으로 형 변환
자동 형변환은 두 데이터 타입이 자동으로 변환이 이루어지는 것을 말한다.
자바에서는 데이터의 손실이 발생하지 않거나 손실이 최소화되는 방향으로 타입 변환을 진행하며 범위가 작은 데이터 값을 더 큰 데이터 타입으로 할당하는 경우에만 동작한다.
char a = 'a';
int num = a;
System.out.println(num) //char 타입의 변수 a가 int형으로 자동 형변환 되어 97 출력
명시적 형변환은 범위가 큰 타입의 값을 작은 타입으로 할당하기 위해서 사용한다.
char a = 'a';
int num = 100;
a = (char)num;
int[] arr1 = new int[5]{1,2,3,4,5}; //1차 배열 선언 및 생성
int[][] arr2 = new int[2][2]{{1,2},{3,4}}; //2차 배열 선언 및 생성
배열은 실제 값이 저장되어 있는 메모리의 주소를 가리키는 배열의 주소를 가지고 있다.
변수의 타입을 명시적으로 적어주지 않아도, 컴파일러가 알아서 이 변수의 타입을 대입된 리터럴로 추론하는 것
컴파일 시점에, 컴파일러가 오르쪽에 있는 초기화 값 리터럴로 타입을 추론한다.
public class test {
public static void main(String[] args) {
var str = "Hello type inference";
if(str instanceof String) {
System.out.println("str 변수의 타입은 String 이다."); //str 변수가 String 타입으로 선언되어 출력된다.
}
}
}
-2. var
public class test {
public static void main(String[] args) {
var var = 3; //에러 발생 X
}
}
자바에서는 컴파일러 에러가 발생한다.
public class test {
public static void main(String[] args) {
var var = 3;
var = "Hello"; //컴파일러 에러 발생
}
}
public class test {
//var 타입은 로컬 변수에만 선언이 가능하다.
var var = "No member variable";
int number = 3;
private void test() {
var var1 = "No member variable";
}
public static void main(String[] args) {
//var는 초기화없이 사용할 수 없다.
var var;
//var 타입 변수에는 null 값이 들어갈 수 없다.
var var = null;
}
}