2주차 항해일지 - 자바 데이터 타입, 변수, 배열

김종하·2020년 11월 15일
2

Live Study - WHITESHIP

목록 보기
3/14
post-custom-banner

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

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

Primitive Type?

기본자료형 혹은 원시자료형 이라고 불리는 프리미티브 타입은 값을 할당할 때 변수의 주소값에 값이 그 자체로 저장되는 데이터 타입이다. 해당 데이터 타입은 값이 할당되면 앞서 살표보았던 JVM Runtime Data Area 영역 중 Stack 영역에 값이 저장된다.

프리미티브 타입의 종류

Java 에서 프리미티브 타입의 종류는 총 8 가지 이다.
byte, short, int, long, float, double, char, boolean 타입이 그것이다. 타입의 종류와 값의 범위 기본값을 다음과 같은 표로 정리해 보았다.

2. 프리미티브 타입과 레퍼런스 타입

Reference Type?

참조자료형 이라 불리는 레퍼런스 타입의 종류는 무한하다. 프리미티브 타입과 달리 JVM Runtime Data Area 영역 중 heap 영역에 할당되는데 레퍼런스 타입의 변수 주소값에는 값이 아닌 heap 영역에 할당된 주소가 저장된다. 조금 더 직관적으로 알아보기 위해 코드를 통해 보도록 하자.

위와 같이 Car 라는 Class 를 생성했다.

다음과 같이 Car 를 인스턴스화 시키면 Heap 영역에 vendor 는 "kia"이고
price 는 100인 객체가 생성되고 car 변수는 단순히 어떠한 값을 저장하고 있는게 아니라 Heap 영역에 저장된 객체의 주소가 저장된다.

int a = 10;
long b = 19.2;
Car c = new Car("kia", 100);

위의 코드를 메모리에 저장되는 모습을 이미지화 시켜보자면 다음과 같다

3. 리터럴

literal?

리터럴은 변수나 상수에 저장되는 값 그 자체를 의미한다.

int a = 10 

에서 바로 10 이 리터럴 인 것이다.

고정된 값을 표현하는 리터럴은 정수를 표현하는 리터럴, 실수를 표현하는 리터럴, 문자를 표현하는 리터럴, boolean 을 표현하는 리터럴, 문자열을 표현하는 리터럴 등이 있다.

정수 리터럴

정수를 표현하는 방법은 여러가지가 있다. 일반적으로 사용하는 10진법 부터 2진법 8진법 과 같은 방법이 있고 자바에서는 다양한 진법을 지원한다.
10진수 26을 다양한 리터럴로 표현해보자.

  int decimal = 26;	   // 일반적인 형태 10진법
  int ocatal = 032;        // 제일 앞에 0 이 붙으면 8진법 
  int heaxaDecimal = 0x1a; // 0x가 붙으면 16진법 
  int binary = 0b11010;    // 0b가 붙으면 2진법 

정수 리터럴은 기본적으로 int 형이고, long 타입을 표현하려면 l,L을 마지막에 붙여야 한다.

실수 리터럴

실수 타입의 리터럴은 기본적으로 double 타입이고, float 타입으로 표현하려면 f를 명시적으로 붙여야한다.

double a = 0.1;				// 0.1
double b = 1E-1;			// 0.1
float c = 0.1f;				// 0.1

문자 리터럴

문자는 작은따옴표(')안에 표현할 수 있다

char a = 'a';				// a 

또 한, 특수문자를 위한 리터럴들도 있다.

참고 - https://mine-it-record.tistory.com/100

문자열 리터럴

문자열은 큰따옴표(")안에 표현할 수 있다.

String a = "abc";		// abc

그런데, 문자열 리터럴에는 조금 특이한 점이 있다. 다른 리터럴들은 프리미티브 타입의 값을 표현하기 위해 존재한다. 그런데 문자열(String)은 레퍼런스 타입이지, 프리미티브 타입이 아니다. 그럼에도 String 타입은 literal 을 지원하는데, literal 방식으로 String 에 값을 주면 Heap 영역에서 String constant pool 이라는 특수한 영역에 값이 저장된다. 그리고, 동일한 값을 쓰는 경우에 다른 일반적인 레퍼런스타입 처럼 Heap 에 또 올라가지 않고, String constant pool 에 존재하는 값을 참조하는 방식으로 작동한다. 자세한 설명은 이전의 포스팅에서 설명한 적이 있기 때문에 링크를 남겨두겠다. https://velog.io/@jaden_94/String-Class

boolean 리터럴

true, false 로 표현할 수 있다.

boolean a = true;
boolean b = false; 

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

Declaration?

변수를 선언한다는 것은, 저장공간을 확보하겠다는 의미로 해석할 수 있다.

int a; 

위의 코드가 변수를 선언한 것인데, 해석하자면 다음과 같다.
int 타입의 값을 저장할 수 있는 공간을 확보했고(int 타입은 4byte) 그 공간을 지칭할 이름은 a 이다.

Initialization?

변수를 초기화 한다는 것은, 저장공간에 원하는 값을 저장하는 것을 의미한다.
변수를 선언하고 나면, 해당 공간에는 아무런 의미 없는 쓰레기값이 들어가있게 된다. 그리고 그 상태에서 컴파일을 시도하면
Error:(10, 28) java: variable a might not have been initialized 와 같은 컴파일 에러코드를 볼 수 있을 것이다.
그러므로 변수는 선언 후에 초기화를 해야하며 위에 선언한 변수에 대한 초기화는 다음과 같이 할 수 있다

a = 10; 

선언과 초기화

변수의 선언과 초기화를 한 줄에 하는 것도 가능하다.

int a = 10; 

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

Scope? LifeTime?

변수의 스코프란 해당 변수를 사용할 수 있는 영역범위를 뜻하고 라이프타임은 해당 변수가 메모리에 언제까지 살아있느지를 의미한다. 변수의 경우 scope 에 따라 Instance Variables, Class Variables, Local Variables 로 나눌 수 있다.

Instance Variables

클래스 안에서 선언되어있고, 어떠한 method나 block안에서 선언되지 않은 변수
scope - static method를 제외한 클래스 전체
lifetime - 클래스를 인스턴스화한 객체가 메모리에서 사라질 때 까지

Class Variables

클래스 안에서 선언되어있고, 어떠한 메서드나 블럭안에서 선언되지 않았으며 static 키워드가 포함되어 선언된 변수
scope - 클래스 전체
lifetime - 프로그램 종료시 까지

Local Variables

인스턴스 변수, 클래스 변수가 아닌 모든 변수
scope - 변수가 선언된 block 내부
lifetime - control 이 변수가 선언된 block 내부에 있는 동안

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;
    }
}

참고 - https://www.learningjournal.guru/article/programming-in-java/scope-and-lifetime-of-a-variable/

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

Type casting?

타입캐스팅이란 크기가 더 큰 자료형을 크기가 더 작은 자료형에 대입하는 것을 의미한다. 예를들어 int(4byte)타입의 데이터를 byte(1byte) 타입에 대입하는 경우가 있을 수 있겠다. 물론, 데이터 크기가 더 크기 때문에 변환과정에서 데이터의 손실이나 변형이 올 수도 있다.

int a = 10;     
byte b = (byte)a;
System.out.println(b); //  -> 10
(byte 는 -256~255까지 표현할 수 있음으로 타입캐스팅을 했음에도 데이터 변형이나 
손실은 오지 않았다) 

	
int a = 10000;     
byte b = (byte)a;
System.out.println(b); //  -> 16
(표현범위를 벗어나는 값을 강제로 타입캐스팅해 데이터에 변형이 생겼다) 

Type promotion?

타입캐스팅과 반대로 크기가 더 작은 자료형을 더 큰 자료형에 대입하는 것을 의미한다. 예를들어 byte(1byte)타입의 데이터를 int(4byte) 타입에 대입하는 경우이다. 그리고 이 경우에는 데이터 손실이나, 변형이 오지 않음으로 캐스팅할 때 처럼 명시적으로 적지 않아도 자동으로 변환이 가능하다.

byte a = 10;
int b = a;
System.out.println(b); //  -> 10

위와 같은 타입변환은 프리미티브 타입뿐만 아니라 레퍼런스 타입에서도 가능하다. 그런데 레퍼런스 타입에도 크기라는 개념으로 캐스팅과 프로모션을 구분지어 생각하면 햇갈릴 수 있다. 부모클래스로의 타입변환은 자동적으로 가능하지만 자식클래스로의 타입변환은 타입캐스팅이 필요하다. 조금만 생각해보면 당연한 이유인데, 자식클래스는 부모클래스의 필드나 메소드를 물려받음으로 자식클래스타입의 객체를 부모클래스타입으로 바꾼다고 해서 데이터의 손실이나 변형이 일어나진 않기 때문이다.

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

Array?

배열이란 동일한 타입의 데이터를 연속된 공간에 저장하기 위한 자료구조이다.

1차 배열의 선언

배열을 선언하기 위해선 [] 을 사용해야한다.

int [] arr1; 
int arr2 []; 

다음과 같이 변수명 앞에 [] 혹은 변수명 뒤에 [] 붙여서 선언하고 초기화는

int [] arr = new int[10];

다음과 같이 배열의 크기를 정해주어야 한다.
위 코드를 해석하자면
int 타입의 연속된 10개의 데이터를 저장하는 공간을 arr 이라는 이름으로 명칭하겠다. 정도로 해석할 수 있겠다.
그리고 배열에는 값을 할당할 수 있는데

arr[0] = 10;
arr[1] = 20;

위와같은 방식으로 값을 할당할 수 있고
선언과 초기화 할당을 한 줄로 할 수 도 이다.

int arr [] = {1,2,3} 

이 코드는 다음 코드와 동일하다

int arr [] = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;

2차 배열의 선언

2차 배열도 1차배열과 유사하며 다음과 같이 사용할 수 있다.

int [][] arr = new int [2][2];
arr[0][0] = 1;
arr[0][1] = 2;
arr[1][0] = 3;
arr[1][1] = 4;

위 코드는 다음 코드와 동일하다 


int arr[][] = {{1,2},{3,4}}

8. 타입 추론, var

타입 추론이란 데이터 타입을 소스코드에 명시하지 않아도, 컴파일 단계에서 컴파일러가 타입을 유추해 정해주는 것을 뜻한다. 1.5버전 부터 추가된 Generic 이나 자바 8 버전에서 추가된 lamda 에서 타입추론이 사용된다. 그리고 자바 10 에서는 이러한 타입추론을 사용하는 var 이라는 Local Variable Type-Inference 가 추가되었다.

var a = "hello";	// String a = "hello";
var b = 10;		// int b = 10;

스터디 주소 : https://github.com/whiteship/live-study/issues/2

post-custom-banner

0개의 댓글