1. Java Data Type
2. 변수(variable) - 선언, 초기화, 스코프, 라이프타임, 타입 변환, 캐스팅
3. 배열 - 1차, 2차
4. 타입 추론
자바에서 기본자료형 혹은 원시자료형이라고 불리며 값을 할당할 때 변수의 주소값에 값이 자체로 저장되는 데이터 타입이다. 해당 데이터 타입은 값이 할당되면 java의 메모리 영역 중 Stack 영역에 값이 저장된다.
종류
참조 자료형이라고 불리며 종류는 무한하다. 무한하다고 불리는 이유는 만들 수 있는 클래스에 대해 적용되는 타입이기 때문이다. 따라서 java의 메모리 영역 중 heap에 메모리가 할당되며 레퍼런스 타입의 변수 주소값에는 값이 아닌 heap 영역의 할당된 주소를 저장하고 있다. 배열, 클래스, 인스턴스 등이 레퍼런스 타입이다.
int a = 1;
float b = 1.0;
Coke c = New Coke("Pepsi"); // Coke라는 클래스가 있다고 가정
위와 같은 코드는 아래와 같은 그림으로 할당 되어있다.
상수(constant)라는 것은 값을 가지는 변수지만 변수 중 한번 값이 지정되고 바꿀 수 없는 변수라고 할 수 있다.
반면에 리터럴(literal)이라는 것은 이러한 변수 및 상수에 저장되는 값 그 자체를 말한다.
public static final float PI = 3.141592f
String s = "JAVA"
위에서 보이는 PI 라는 것은 상수이고, 3.141592, "JAVA" 에 해당하는 것이 리터럴 이라고한다. 특성에 따라서 정수 리터럴, 실수 리터럴, 문자열 리터럴 등으로 부른다.
변수라는 것은 데이터를 저장하기 위해 프로그램에 의해 이름을 할당 받은 메모리 공간이라고 할 수 있다. 즉 변수가 선언이 되면 메모리에 공간을 할당하게 되고 초기화를 하면 데이터 값이 할당된 공간에 저장이 된다.
int a; // 변수 선언(Declaration)
a = 10; // 변수 초기화(initialize)
int a =10; //변수 선언 및 초기화
프로그램상에서 사용되는 변수들은 사용 가능한 범위를 가지게 된다. 그 변수의 범위를 스코프라고 한다.
변수가 선언된 블럭이 그 변수의 사용 범위이다.
public class globalScopeClass(){
int globalScope = 10;
public void inerScopeClass(int x){
int localScope = 10;
System.out.println(globalScope);
System.out.println(localScpe);
System.out.println(x);
}
}
public class globalScopeClass(){
int globalScope = 10;
static int staticVar = 10;
public void inerScopeClass(int x){
int localScope = 10;
System.out.println(globalScope);
System.out.println(localScpe);
System.out.println(x);
}
public static void main(){
System.out.println(globalScope); // 오류
System.out.println(localScpe); // 오류
System.out.println(x); // 오류
System.out.println(staticVar); // 오류
}
}
static
public class scope_and_lifetime {
int num1, num2; //Instance Variables
static int result; //Class Variable
int add(int a, int b){ //Local Variables
num1 = a;
num2 = b;
return a+b;
}
public static void main(String args[]){
scope_and_lifetime ob = new scope_and_lifetime();
result = ob.add(10, 20);
System.out.println("Sum = " + result);
}
}
여러 변수가 있고 변수간의 타입이 다를 수 있다. 예를 들면 int와 float타입의 변수가 존재한다고 하면
두개의 변수가 저장하는 방식이 다를 수 있다. 그럴 경우 캐스트 연산자라는 것을 사용하게 되는데 이것 하나의 변수를 다른 변수의 저장 방식으로 바꿔주는 연산자이다. 즉 이런 특정 자료형을 다른 자료형으로 변경하는 방법을 타입 캐스팅, 한국말로 형변환이라고 한다.
기본적으로 프리미티브 타입들의 타입캐스팅은 모두 형변환이 가능하다. 물론 데이터의 손실 및 오차가 발생할 수는 있다.
하지만 클래스 타입들은 조금 다르다. 일반적인 클래스끼리는 타입캐스팅이 불가능하다.
상속관계를 가지고 있는 클래스끼리의 타입캐스팅이 가능하다. (추후 상속 관련에서 자세히 다루도록하자)
간단한 규칙만을 알고 넘어가자.
클래스의 타입캐스팅 규칙
1. 부모클래스는 명시적인 타입캐스팅 없이 자식과 연결 할 수 있다. 업캐스팅(Up-Casting)
2. 자식클래스는 명시적인 타입캐스팅이 있다면 부모와 연결 할 수 있다. 다운캐스팅(Down-Casting)이라 한다.
3. 상속관계가 아니면 타입캐스팅은 불가능하다.
배열은 동일한 자료형의 데이터를 연속된 공간에 저장하기 위한 자료구조이다. 즉, 연관된 데이터를 그룹화하여 묶어준다고 생각할 수 있다.
//int 타입 배열 선언
int[] array;
int array[];
//배열 생성후 초기화하면 배열의 주소가 할당된다.
int[] i = new int[20]; //초기값 0
String[] s = new String[20]; //초기값 ""
//배열 선언만 해놓고 나중에 초기화를 시킬수도 있다.
int[] x;
x = new array[8];
위와 같이 다양한 방식으로 배열을 선언, 초기화 할 수 있다.
즉, 요약하면 배열은
타입 [] 변수명;
타입 변수[];
두가지 방식으로 선언이 가능하다.
위에서 사용하게 된 배열은 1차원 배열이다. 기본적으로는 1차원 배열을 주로 사용하지만 그것을 넘어서 여러 다차원의 배열을 사용하게 되는 경우가 있다.
예를 들어 int[][] arr = new int[3][4]라는 배열을 생각 해보자.
3개의 배열이 각각 4개의 값을 가지고 있다라고 생각할 수 있다.
와 같이 생각 할 수있다.
1차원 배열과 마찬가지로 선언시 []위치는 자유롭게 설정할 수 있다.
int [][]arr;
int []arr[];
int arr[][];
위와 같은 형태로 선언이 가능하다는 것을 알아두면 좋다.
실제 사용은 첫 번째를 사용하는 것이 좋다.
자바 버전 9이하에서는 Generic과 lambda를 사용할 때 타입추론을 이용한다.
타입추론이란 코드 작성시 타입이 지정되지는 않지만, 컴파일러가 그 타입을 유추하는 것이다.
자바 10부터 타입 추론을 지원하는 var 키워드가 추가되었다. 이 키워드는 local variable 이면서 선언과 동시에 initializer가 필수적으로 요구된다.
// java 9 이하
String msg = "abcd";
// java 10 이상
var msg = "abcdefg";
주의 요구
// 컴파일러가 타입을 유추할 수 있는 정보 X
var msg = new ArrayList<>();