<Java> 자바 데이터 타입, 변수 그리고 배열

라모스·2021년 8월 23일
0

Java☕

목록 보기
2/14
post-thumbnail

" 자바의 프리미티브 타입, 변수 그리고 배열을 사용하는 방법을 익힙니다. "

학습할 것

  • 프리미티브 타입 종류와 값의 범위 그리고 기본 값
  • 프리미티브 타입과 레퍼런스 타입
  • 리터럴
  • 변수 선언 및 초기화하는 방법
  • 변수의 스코프와 라이프타임
  • 타입 변환, 캐스팅 그리고 타입 프로모션
  • 1차 및 2차 배열 선언하기
  • 타입 추론, var

1. 프리미티브(기본형) 타입 종류와 값의 범위 그리고 기본 값

자바의 기본 타입은 총 8개이다. 기본형에는 기본값이 존재하기 때문에 NULL 값이 존재하지 않고 실제 값은 스택 메모리에 저장되며 만약 담을 수 있는 크기보다 큰 값을 넣으려고 하면 컴파일 에러가 발생한다.

첫 번째 비트는 부호(1: 음수 / 0: 양수)를 나타내고 나머지 비트들을 이용하여 수를 표현하게 된다. 양수에 0을 포함하여 계산하기 때문에 부호있는 정수형의 표현 범위는 -2^n ~ 2^n -1 가 된다.

// 출처: 명품 Java Programming

2. 프리미티브(기본형) 타입과 레퍼런스(참조형) 타입

레퍼런스(reference)란 C/C++의 레퍼런스와 동일한 개념이고 포인터와 유사하다. Java에선 실제 값이 저장되어 있는 곳의 위치를 저장한 값(주소 값)을 뜻한다. 참조형 타입의 종류는 배열, 클래스, 인터페이스에 대한 레퍼런스가 있다. 앞서 서술했던 기본형 타입은 저장되는 값이 실제 값 그 자체이지만, 레퍼런스 타입은 메모리의 주소값을 저장하고 있다는 점에 차이가 있다.

// 참고로 문자열은 기본타입이 아니다.

기본타입과 참조타입의 값은 JVM의 Runtime Data Area에 저장되는데, 각각 runtime stack 영역과 garbage collector heap 영역에 저장된다.

3. 리터럴

리터럴은 데이터 그 자체를 의미한다. 정수, 실수, 문자, 논리, 문자열 리터럴이 있고 프로그램에서 직접 표현한 값으로 그 자체로 메모리에 저장되어있어 변하지 않는 값을 뜻한다.
// 상수와 혼동하면 안되는 개념임.

// 정수 리터럴(int 형으로 컴파일 함)
int n = 15;    // 10진수 리터럴 15
int m = 015;   // 8진수. 십진수로 13
int k = 0x15;  // 16진수. 십진수로 21
int b = 0b0101; // 2진수. 십진수로 5
// long 타입 리터럴은 숫자 뒤에 L 또는 l을 붙여 표시함
long g = 24L;

// 실수 리터럴(double 타입으로 컴파일 함)
// 소수점 형태나 지수 형태로 표현한 실수
double d = 0.1234;
double e = 1234E-4; // 1234*10^-4 이므로 0.1234와 동일
// 숫자 뒤에 f(float), F, d(double), D를 명시적으로 붙이기도 함
float f = 0.1234f;
double w = .1234D;

// 문자 리터럴(단일 인용부호(' ')로 문자 표현)
// 한 글자는 2 byte 크기임
char a = 'A';
char b = '글';
char c = \u0041; // 문자 'A'의 유니코드 값(0041) 사용
char d = \uae00; // 문자 '글'의 유니코드 값(ae00) 사용

// 논리 리터럴(자바는 0,1 대신 true/false를 사용함)
boolean a = true;
boolean b = 10 > 0; // 10 > 0 값은 참이므로 b는 true

// 문자열 리터럴(이중 인용부호로 묶어서 표현)
// 문자열 리터럴은 String 객체로 자동 처리
String str = "good";

4. 변수 선언 및 초기화하는 방법

변수: 프로그램 실행 중에 값을 임시 저장하기 위한 공간

변수를 선언한다는 것은 메모리에 데이터를 저장할 공간을 지정해 주는 것이다. 데이터 타입에서 정한 크기의 메모리를 할당한다. 변수의 종류는 클래스 변수, 인스턴스 변수, 지역 변수로 나눌 수 있는데 먼저 클래스 변수는 클래스가 참조될 때 활용되어 전체 클래스에 적용되고 인스턴스 변수는 객체가 생성될 때 같이 생성된다. 지역변수는 메소드 안에서 선언되고 메소드 안에서만 사용가능하다.

초기화 하는 방식은 다음과 같다.

// 변수타입 변수명;
int a;

// 명시적 초기화
// 변수타입 변수명 = 초기화할 값;
int b = 0;

// 생성자 활용 초기화
ClassA ca = new ClassA();
ca.a = 1;
ca.b = 'A';
ca.c = "RONALDO";
// 만약 기본 생성자가 아닌 매개변수가 정해진 생성자가 정의되어 있다면 다음과 같이 초기화 가능
ClassA ca = new ClassA(1, 'A', "RONALDO");

// 초기화 블록을 활용한 클래스, 인스턴스 변수 초기화
class ClassA {
    static { } // 클래스 초기화 블럭
    {        } // 인스턴스 초기화 블럭
}

5. 변수의 스코프와 라이프타임

변수의 스코프란 변수에 대해 접근과 변수가 존재할 수 있는 영역을 의미한다. 클래스 변수, 인스턴스 변수, 지역 변수로 나눌 수 있는데, 이런 변수의 종류를 결정하는 것은 '변수가 선언된 위치'가 결정하게 된다.

클래스 변수와 인스턴스 변수는 클래스 내부에 선언해야 하는데, 그 중 클래스 변수는 static을 앞에 붙여서 선언해 주어야 한다. 지역변수는 메소드 안에서 선언을 하면 지역변수로 선언된다.

변수의 종류선언 위치생성 시기(메모리 할당 시기)변수의 스코프
클래스 변수클래스 영역클래스가 메모리에 올라갈 때클래스 전역(클래스 기반으로 생성된 각각의 인스턴스에 공유됨)
인스턴스 변수클래스 영역인스턴스가 생성될 때각각의 인스턴스
지역 변수메소드 영역변수의 선언문이 수행되었을 때메소드 안

각각의 변수의 라이프타임은 클래스 변수의 경우, 프로그램이 종료할 때 까지 적용되고 인스턴스 변수의 경우는 인스턴스가 참조되고 있을때에는 유지되다가 객체를 참조하는 변수가 없을 경우 JVM의 Garbage Collecor가 제거하게 된다. 지역변수의 경우 메소드가 끝나면 소멸되어 사용할 수 없게 된다.
// OS의 메인 메모리 구조와 연관지어 생각해보자.

6. 타입 변환, 캐스팅 그리고 타입 프로모션

타입 변환은 자바의 연산에 도움을 주기 위한 방법이다. 자바에서 연산은 동일한 데이터 타입에서만 가능하지만, 코드를 짜다보면 서로 다른 데이터 타입끼리의 연산이 필요로 한 경우가 있다. 이 때 사용하는 것이 타입 변환으로 캐스팅(강제 형변환)과 타입 프로모션(자동 형변환)이 있다.

  • 타입 프로모션: 자신의 표현 범위를 모두 포함한 데이터 타입으로의 변환

  • 타입 캐스팅: 자신의 표현 범위를 모두 포함하지 못한 데이터 타입으로의 변환

타입 프로모션은 프로그램을 실행하면 자동적으로 형변환이 일어나는 것이다. 작은 메모리 크기의 데이터 타입을 큰 메모리 타입으로 변환시키게 된다. 이것은 컴파일러에 의해 이루어지고 치환문(=)이나 수식 내에서 타입이 일치하지 않을 때 발생한다. 자동 형변환이 이루어지는 순서는 다음과 같다.
byte(1) < short(2) < int(4) < long(8) < float(4) < double(8)

long m = 25;  // 25는 int 타입에서 long타입으로 자동 변환됨

// 실수 연산을 하기 위해 10이 10.0으로 자동 변환
// 다른 피연산자 3.14가 실수이기 때문
double d = 3.14 * 10;

타입 캐스팅은 타입 프로모션이 안 되는 경우(큰 타입을 작은 타입으로 변환할 때) 연산을 하기 위해 개발자가 강제로 타입 변환을 지시하여 형변환을 시켜주는 것이다. 강제 변환은 값 손실의 위험성이 있다. 표현할 범위가 더 작은 데이터타입으로 변환하여 넣을 때 작은 데이터타입의 표현 범위를 벗어나게 되면 입력한 데이터와는 전혀 다른 값이 나올 수도 있다는 것이다.

int n = 300;
byte b = n; // 컴파일 오류. int 타입에서 byte로 자동 변환 안됨.

byte b = (byte) n;


// 타입 캐스팅시 발생할 수 있는 값 손실 (출처: 명품 Java Programming)

7. 1차 및 2차 배열 선언하기

자바에서 배열의 선언은 두 가지 방법으로 가능하다. 다음과 같다.

int[] array;
int array[];

이처럼 선언하면 배열은 null 값을 가지고 있고 이후 초기화를 하면 배열의 주소가 할당되어 사용할 수 있게 된다.

초기화의 방식은 다음과 같다.

// 배열의 선언 및 생성
int[] array = new int[3];

// 배열의 선언, 생성 및 초기화
int[] array = {0, 1, 2};
// 또는
int[] array;
Arrays.fill(array, 1);
// 또는
for(int i = 0; i < array.length; i++)
    array[i] = i;


// 2차원 배열도 마찬가지로 선언하고 생성한다
int[][] a = new int[2][3];
int[][] b = {{1, 2}, {3, 4, 5}};
int[][] c = new int[][] {{1, 2}, {3, 4, 5}};

하나의 배열을 다수의 레퍼런스가 참조 가능하다.


// 레퍼런스 대입과 배열 공유

추가로 Java에서 배열은 객체로 관리한다. 배열 객체 내에 length 필드는 배열의 크기를 나타낸다.

// 배열 객체

8. 타입 추론, var

타입 추론이란 코드 작성 당시에는 타입이 정해지지 않았지만, 컴파일러가 그 타입을 유추하는 것을 의미함. 대표적으론 제네릭에서 많이 사용한다. 주의해야 할 점은 var는 지역변수로 사용해야 하고 선언과 동시에 초기화가 필요하다. Java 9까지는 generics나 lamda식에 대해서만 타입추론을 지원했지만 Java 10부터 타입추론을 지원하는 var이라는 키워드가 추가되어 자바에서도 타입추론을 사용가능하게 되었다.

// Java 10에서 var 사용하기와 관련된 글
https://dev.to/composite/java-10-var-3o67
https://dev.to/composite/java-10-var-2-4f8a

References

  • 명품 Java Programming
  • Java의 정석 3판
profile
Step by step goes a long way.

0개의 댓글