Skip to content

Latest commit

 

History

History
285 lines (172 loc) · 12.4 KB

Java_Study_02.md

File metadata and controls

285 lines (172 loc) · 12.4 KB

2주차. 자바 데이터 타임, 변수 그리고 배열

학습할 것

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





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

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

표현범위를 계산하는 방법은 메모리 크기에 연관되어 있습니다.

부호를 표현한다면 첫번째 비트는 부호를 나타나게 되어 나머지 n-1의 비트를 이용하여 수를 표현하게 됩니다. 또한 양수에 0을 포함하여 계산하기 때문에 부호있는 정수형의 표현 범위는 -2 n ~ 2 n -1 가 됩니다.

타입 메모리크기 기본값 표현 벙위
정수형 byte 1 byte 0 -2 7 ~ 2 7 -1
정수형 short 1 byte 0 -2 15 ~ 2 15 -1
정수형 int (기본) 4 byte 0 -2 31 ~ 2 31 -1
정수형 long 8 byte 0L -2 63 ~ 2 63 -1





실수형에서는 값을 부호, 지수, 가수로 나누어 저장됩니다. 따라서 같은 크기임에도 훨씬 큰범위를 표현 가능하지만 실수형은 원래 저장하려던 값과 실제 저장된 값이 오차가 날 수 있습니다. 그래서 오차없는 자리 수인 정밀도가 굉장히 중요한데 정밀도를 계산하는 방법은 가수 부분의 데이터크기에 관련되어 있습니다.

위의 이미지에서 처럼 실수형 float의 가수부분은 23비트인데 여기서 정규화를 통해 24까지 표현이 가능합니다. 2 24은 10 7 보다는 크고 10 8 보다는 작기에 float의 정밀도는 7이 됩니다. double의 경우에는 가수부분이 52비트이고 위와 같은 계산을 통하여 정밀도를 계산하면 정밀도는 15자리가 됩니다.

따라서 변수를 선언할때 실수의 정밀도를 반드시 고려하여 선정해야할 필요가 있습니다.

타입 메모리크기 기본값 표현 벙위 정밀도
실수형 float 4 byte 0.0F -3.4E38 ~ -1.4E-45, 1.4E-45 ~ 3.4E38 7자리
실수형 double (기본) 8 byte 0.0 (1.7 * 10 -308 ) ~ (1.7 * 10 308 )의 근사값 15자리





나머지 타입으로는 논리형 boolean과 문자형 char가 있습니다. 논리형 boolean은 참,거짓을 판단하기 때문에 1bit이면 충분하지만 Java가 데이터를 다루는 최소 범위가 1 byte이기 때문에 1 byte를 할당합니다. 문자형 char는 유니코드를 사용하기 때문에 유니코드의 요구 범위인 2 byte가 필요로 하여 2byte를 할당합니다.

타입 메모리크기 기본값 표현 벙위
논리형 boolean 1 byte false true, false
문자형 char 2 byte '\u0000' 0 ~ 65,535





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

앞서 살펴본 기본형 타입은 이미 Java에서 정의되어있는 데이터 타입으로 변수를 선언 할때 메모리에 고정된 크기로 저장되고 변수에 데이터의 값을 저장하게 됩니다. 하지만 참조형 타입은 변수를 선언할때 크기가 정해져있지 않고 값이 변수가 할당될때 저장할 메모리에 대한 주소가 저장되어 있습니다.

위의 그림같은 형태로 구성되어 저장된 변수의 주소값을 참조하여 활용하게 됩니다. 또한 기본형 데이터타입과 참조형 데이터타입은 JVM Runtime Data Area에서 데이터를 저장하고 생성하는 위치가 다른데 기본형 데이터타입의 경우 Thread Area 안에 스택 영역에 생성이 되고 참조형 데이터타입은 힙영역에서 생성되게됩니다.





1-3. 리터럴

리터럴은 데이터 그 자체를 의미합니다. 상수와 많은 착각을 일으키고는 하는데 상수의 경우 한 번만 값을 저장 가능한 변수를 의미하고 리터럴의 경우 데이터 그자체를 의미하기 때문에 차이가 있습니다. 예를 들어 아래의 코드에서 int에 대입하는 1이 리터럴이 되는 것이며 앞에 final을 붙이면 상수가 되는 것입니다. 따라서 각각의 변수 타입에 따라 표현범위에 있는 값이 리터럴로 입력 가능합니다.

int a = 1;        //리터럴은 1
final int a = 1;  //상수로 선언





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

변수를 선언한다는 것은 메모리에 데이터를 저장할 공간을 지정해 주는 것입니다. 변수를 선언하는 방식은 아래 코드와 같습니다.

변수타입 변수명;
ex) int a;

이렇게 변수가 선언되면 변수타입에 해당하는 크기만큼 메모리에 용량이 할당됩니다.

변수의 종류는 클래스 변수, 인스턴스 변수, 지역 변수로 나누어 볼수 있습니다. 먼저 클래스 변수는 클래스가 참조될때 활용되어 전체 클래스에 적용되고 인스턴스 변수는 객체가 생성될때 같이 생성됩니다. 지역변수의 경우에서는 메소드안에서 선언되고 메소드안에서만 사용가능합니다.

선언된 변수는 클래스 아래에 선언된 인스턴스 변수의 경우는 1-1의 표에서 확인한 기본값이 저장되어 있는 상태이지만 지역변수의 경우는 반드시 초기화가 필요합니다.
초기화하는 방식은 명시적 초기화, 생성자, 초기화 블럭을 활용하는 방법이 있습니다.

명시적 초기화

변수타입 변수명 = 초기화할 값;
ex) int a = 0;

생성자 활용 초기화

ClassA ca = new ClassA();
ca.a = 1;
ca.b = 'A';
ca.c = "KSB";
//만약 기본 생성자가 아닌 매개변수가 정해진 생성자가 정의되어 있다면 이렇게 초기화 할 수 도 있다.
ClassA ca = new ClassA(1,'A',"KSB");

초기화블록을 활용한 클래스, 인스턴스 변수 초기화

class ClassA{
    static { } //클래스 초기화 블럭
    {        } //인스턴스 초기화 블럭
}





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

변수의 스코프란 변수에 대하여 접근과 변수가 존재할 수 있는 영역을 의미합니다. 이런 변수의 스코프로 구분해보면 클래스 변수, 인스턴스 변수, 지역 변수로 나누어 볼 수 있습니다. 이런 변수의 종류를 결정하는 것은 '변수가 선언된 위치'가 결정하게 됩니다.

먼저 클래스 변수와 인스턴스 변수는 클래스의 내부에 선언하여야 하는데 그중 클래스 변수는 static을 앞에 붙여서 선언해주어야 합니다. 지역변수는 메소드 안에서 선언을 하면 지역변수로 선언되게 됩니다.

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



각각의 변수의 라이프타임은 클래스 변수의 경우 프로그램이 종료할때까지 적용되고 인스턴스 변수의 경우는 인스턴스가 참조 되고 있을때에는 유지되다가 객체를 참조하는 변수가 없을 경우 JVM의 Garbage Collector가 제거하게 됩니다. 지역변수의 경우 메소드가 끝나면 소멸되어 사용할 수 없게 됩니다.





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

타입 변환은 자바의 연산에 도움을 주기 위한 방법입니다. 자바에서 연산은 동일한 데이터 타입에서만 가능합니다. 하지만 프로그램을 구성하다보면 서로 다른 데이터 타입끼리의 연산이 필요로 한 경우가 있습니다. 이럴때 필요한 것이 타입 변환으로 종류로는 캐스팅(강제 형변환)과 타입 프로모션이 있습니다(자동 형변환).

먼저 타입 프로모션은 프로그램을 실행하면 자동적으로 형변환이 일어나는 것입니다. 타입 프로모션은 작은 메모리 크기의 데이터 타입을 큰 메모리 타입으로 변환시키게 됩니다. 먼저 예를 한번 들어보겠습니다.

byte a = 10;
int b = a; 

이런 경우에는 1byte의 byte타임을 4byte인 int에 넣기 때문에 별다른 오류나 문법의 필요없이 형변환이 자동으로 이뤄지게됩니다. 이처럼 자동 형변환이 이루어지는 순서는 다음과 같습니다.

byte(1) < short(2) < int(4) < long(8) < float(4) < double(8)

float와 double의 경우는 용량은 작지만 표현할 수 있는 값이 더 크기 때문에 자동형변환이 가능합니다. 또한 문자형을 정수로 변환하게되면 유니코드 값이 저장되게 됩니다.

다음으로 캐스팅은 타입 프로모팅이 이뤄지는 경우를 제외한 상황에 연산을 하기위해 강제로 형변환을 시켜주는 것입니다. 캐스팅의 문법은 변환시킬 변수 앞에 괄호하고 변환하고자 하는 데이터 타입을 적으면 변환시키게됩니다. 여기서 주의해야 할것은 표현할 범위가 더 작은 데이터타입으로 변환하여 넣을때 작은 데이터타입의 표현 범위를 벗어나게되면 입력한 데이터와는 전혀 다른 값이 나올수도 있어 주의해야합니다.

위 그림을 보면 넣은 값은 7410이지만 강제 형변환으로 앞의 1byte가 사라져 11110010(2) 가 남게되며 첫자가 1이기 때문에 음수로 판단되어 실제값은 2의 보수인 -14라는 값이 출력됩니다.





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

자바에서 배열의 선언은 두 가지 방법으로 가능합니다. 변수 선언에서 데이터타입 뒤에 []를 입력하는 방법과 변수 명뒤에 []를 입력하는 방법입니다.

int[] array;   //가능
int array[];   //가능

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

int[] array = new int[3];
// OR
int[] array = {0, 1, 2};
// OR
int[] array;
Arrays.fill(array,1);
// OR
for(int i=0;i<i_array.length;i++) {
    array[i]=i;
}

2차원 배열도 크게 다르지 않습니다. []를 추가해주는 것으로 2차원,3차원 배열을 구성할 수 있습니다.

int[][] array;   //가능
int array[][];   //가능

2차원 배열의 초기화 방법입니다.

int[][] array = new int[4][3];
// OR
int[][] array = [{0, 1, 2},{3,4,5},{6,7,8},{9,10,11}];
// OR
for(int i=0;i<array.length;i++) {
    for(int j=0;j<array[i].length(); j++)
        array[j]=j;
    }
}





1-8. 타입 추론, var

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