목적
자바의 프리미티브 타입, 변수 그리고 배열을 사용하는 방법을 익힙니다.
프리미티브라는 한글말만 보고 커피에 타먹는 가루 용어인가 그래서 어원 비슷하게 쓰는가 생각했는데.. 검색해보니 ‘primitive = 기본적인, 원시적인’ 이라는 뜻이라니.. 잠깐 누구도 보지 않았는데 영어가 부족한 내가 부끄러운 순간이었다..
학습할 것
프리미티브 타입 종류와 값의 범위 그리고 기본 값
일단은 정신을 다잡고 primitive 타입을 알아보기 전 일단 변수의 타입에 대해서 알아보자
우리가 사용하는 값은 문자와 숫자로 나뉘어지고 값의 종류에 따라 저장될 공간의 크기와 저장형식을 정의한 것이 자료형이다. 자료형에는 문자형, 정수형, 실수형이 있으며 가장 알맞은 자료형을 변수의 타입으로 선택하면 된다.
자료형은 기본형(프리미티브 타입)과 레퍼런스 타입으로 나뉘는데 이 둘의 비교는 나중에 하고 프리미티브 타입에 대해서 알아보자
프리미타입은 모두 8개의 타입이 있으면 논리형, 문자형, 정수형 실수형으로 구분된다.
프리미티브 타입 종류, 기본값
분류 | 타입 |
---|---|
논리형 | boolean true와 false 둘 중 하나의 값으로 갖으며 조건식과 논리적 계산에 사용된다. |
문자형 | char 문자를 저장하는 데 사용되며 변수에 하나의 문자만 저장 |
정수형 | byte, short, int, long 정수를 저장하는데 사용되며 주로 int가 사용된다. byte는 이진 데이터 다룰 때 사용되며, short는 C언어와 호환을 위해서 추가되었다. |
실수형 | float, double 실수를 저장하는데 사용되며, 주로 double이 사용된다. |
Primitive type 범위
1byte | 2byte | 4byte | 8byte | |
---|---|---|---|---|
논리형 | boolean | |||
문자형 | char | |||
정수형 | byte | short | int | long |
실수형 | float | double |
값의 범위
자료형 | 저장 가능한 값의 범위 | bit | byte |
---|---|---|---|
boolean | false, true | 8 | 1 |
char | ‘\u0000’ ~ ‘\uffff’ (0 ~ 2^16 -1, 0 ~ 65535) | 16 | 2 |
byte | -128 ~ 127 (-2^7 ~ 2^7-1) | 8 | 1 |
short | -32,768 ~ 32,767 (-2^15 ~ 2^15 -1) | 16 | 2 |
int | -2147483648 ~ 2147483647 | 32 | 4 |
long | -9223372036854775808 ~ 9223372036854775807 | 64 | 8 |
float | 3.4E-38(-3.410^38) ~ 3.4E+38(3.410^38) | 32 | 4 |
double | 1.79E-308(-1.7910^308) ~ 1.79E+308(1.7910^308) | 64 | 8 |
프리미티브 타입과 레퍼런스 타입
프리미티브가 기본형이라고 하면 레퍼런스는 그래도 참조형이라고 알고 있다! 여튼 위에 프리미티브 타입에 대해 적었기 때문에 레퍼런스 타입에 대해서 이야기 하자면, 레퍼런스 타입은 어떤 값이 저장되어 있는 주소(memory address)를 값으로 갖는다. 즉 주소를 따라가 적혀있는 값을 사용한다고 생각하면 된다.
참조형 변수를 선언할 때는 변수의 타입을 클래스로 사용해 클래스 이름이 참조변수의 타입이 된다. 즉 새로운 클래스는 새로운 참조형을 추가한다 봐도 된다.
Date today = new Date();
여기서 이 코드의 뜻은 Date 객체를 생성해서 그 주소를 today에 저장이라고 하면 된다.
그리고 참조변수 today를 통해 생성된 객체를 사용할 수 있게 된다.
여기서 프리미티브랑 레퍼런스 차이를 조금 더 추가해서 이야기 하자면, 프리미티브는 date type을 쓰며 레퍼런스의 참조형은 항상 객체의 주소(4byte 정수)를 저장하여 객체의 종류에 의해 구분되므로 type이라는 용어로 사용한다. 허나 타입이 자료형보다 포괄적 의미이므로 굳이 구분할 필요는 없다.
리터럴
리터럴은 일단 상수랑 비교해야 하는데 상수는 프로그래밍에선 값을 한번 저장하면 변경할 수 없는 고유 값이라고 생각하면 된다. ex) final int WIDTH = 20;
그래서 리터럴이 무엇이냐 하면 데이터 그 자체를 말한다. 즉, 위 WIDTH 예시에서 20의 값을 final로 넣은 WIDTH는 상수이고 저 20 이라는 값은 우리가 20이라는 뜻을 세상을 바꾸지 않는 한 변하지 않는 값이 ‘리터럴’이라고 말할 수 있다.ex) 1L (Long타입으로 지정하는 숫자 1)
재미있는건 리터럴의 타입은 저장될 변수의 타입과 일치하는 것이 보통이지만, 타입이 달라도 저장 범위가 넓은 타입에서 좁은 타입으로 저장은 허용된다는 것이다. ex) int i = ‘A’;
변수 선언 및 초기화하는 방법
일단 변수에 대해 뜻을 한번 적어보자면 ‘단 하나의 값을 저장할 수 있는 메모리 공간’ 이라고 정의한다. (그냥 일단 적어봤다)
변수 선언
int age;
이렇게 코드에 적어주면 변수를 선언했다고 말한다.
저기서 int 라고 적어 준 것이 변수 타입이며 저장하고자 하는 값에 맞게 타입을 선택해서 적어주면 된다. 그다음 age 라고 적어 준 것이 변수 이름이며 뜻에 적어놓은 메모리 공간에 붙여준 이름이라고 생각하면 된다. 저 age로 가져오고 저장하는 일을 할 수 있다.
변수의 초기화
변수의 초기화란, ‘변수를 사용하기 전에 처음으로 값을 저장하는 것’ 이며, 뜻 처럼 변수를 선언한 후엔 변수 사용을 할 수 있으나 그 전에 변수를 초기화 해주어야 한다. 메모리는 여러 프로그램에 의해 저장된, ‘알 수없는 값’이 남아 있을 수 있기 떄문이다.
int age = 25;
변수의 종류에 따라 초기화를 생략할 순 있지만, 사용되기 전엔 값을 초기화 시켜주는 것이 좋다.
변수 의 스코프와 라이프타임
스코프
스코프란 뜻은 잘 몰라서 검색해보니 영역이라는 뜻을 가지고 있다. 영역이면 흠.. 백기선님이 말한 변수의 스코프 = 변수의 영역 이면 변수가 쓰이는 공간.. 그러면 한 공간에서 쓰이는 변수의 공간, 영역이면 기본 클래스를 배울 때 class에 선언한 변수는 class 안의 함수에서 쓸 수 있지만, class 내 method 에 선언한 변수는 클래스 밖으로 가져 올 수없다. 이런건가 라고 생각한다.
그리고 이젠 검색해서 찾아보면, 예상이랑 비슷하게 자바 변수가 가질 수 있는 활동 영역이 있고 이걸 스코프라 부른다. 스코프의 종류는 메소드 스코프랑 클래스 스코프로 나뉜다.
- 메소드 스코프 : 메소드 내에서 선언해 메소드 내에서만 돌아다니는 영역
- 클래스 스코프 : 클래스 내부에 있는 곳을 전부 다 돌아다닐 수 있는 영역
예를 들어 account 클래스가 있고 생성자를 만들어 주려고 한다. (이름을 넣어주는 생성자)
public Class Account{
String name;
public Account(String name){
name = name;
}
}
이런 식으로 되어 있으면 생성자 내에 있는 name = name; 부분을 보자. 앞의 name은 사실 우리가 원하는 Account 클래스 내의 name에 파라미터로 받아온 값을 클래스 스코프의 name에 넣고 싶은데 저렇게 쓰면 name을 쓰면 파라미터에 파라미터를 넣게 되어버린다. 왜냐면 같은 메소드 스코프 내에서의 name에 name 을 넣겠다는 뜻이기 때문에
우리는 이때 써야할 것은 this가 있다. 이 this라는 것은 자기 자신 객체를 가리키는 키워드로써
this.name = name;
라고 적어주면 우리가 원하는 방식대로 name을 넣을 수 있다.
라이프타임
라이프타임은 내가 구글링이 부족한 지 정보를 잘 알아 낼 수 없어 남들이 올린 과제를 좀 읽어보기로 했다. (센세.. 나 잘하고 있는거 맞죠?) 일단은 여러 글들을 읽어보니 데이터가 살아 있는 시간, 즉 가비지 컬렉터가 돌아가기 전까지의 시간이라고 써져있다. 그리고 라이프 타임이 적용되는 3가지 변수가 있는데 인스턴스 변수, 클래스 변수, 지역변수가 있다.
변수 | 범위 | 생성시기 | 종료시기 |
---|---|---|---|
클래스 변수 | 클래스 | 클래스 메모리 선언시 | 프로그램 종료 시 |
인스턴스 변수 | 클래스 | 인스턴스 생성 | GB 실행 시 |
지역 변수 | 메서드, 생성자, 블럭 | 변수 실행 | 선언된 범위 넘어갈 때 |
타입 변환, 캐스팅 그리고 타입 프로모션
타입변환
‘하나의 타입을 다른 타입으로 바꾸는 것’ 이라고 한다. 자바에서는 논리형 boolean을 제외한 나머지 기본 타입 간 타입변환이 자유롭게 된다.
여기서 하나 주의할 것은 다른 타입끼리의 연산을 수행할려고 하면 피 연산자들을 같은 타입으로 만들어 진행합니다. 그래서 메모리에 할당받은 바이트 크기가 상대적으로 작은 타입에서 큰 타입으로 변경은 생략할 수 있다. 허나 반대인 경우에는 큰 것을 작은 것에 넣다 보니 데이터 손실이 일어난다는 것이다. 따라서 이 때는 자바 컴파일러가 오류를 발생시킨다.
캐스팅
프로그래밍시 가른 타입간의 연산을 수행해야 하는 경우가 있는데, 이때 타입을 일치시켜야 하는데 이거를 캐스팅(형변환)이라고 한다.
방법은 간단히 ‘(타입)피연산자’ 로 정의하며 피 연산자를 타입형으로 바꿨을 땐 값만 변해서 읽을 뿐, 변화는 없다.
그리고 기본형과 참조형은 서로 형변환을 할 수 없다.
타입 프로모션
타입 프로모션.. 이럴수록 영어에 대해 참 막막해질 때가 있다. 처음엔 오 새로운건가 했다가 자동 형변환이라는 해석을 듣고 당황;; 허나 일단은 이걸 적어놓으면 담엔 안헷갈리겠지 하며 적는다.
타입 프로모션은 한국말로 자동 형변환라고 불리며 편의상의 이유로 형변환을 생략하는데 진짜 생략이 아니라 컴파일러가 생략된 형변환을 자동으로 추가해준다.
근데 재밌는건 명시적으로 형변환 해줬을 경우는 의도적인 것을 알고 컴파일러는 에러를 발생시키지 않는다.
char ch = (char)1000;
일단 컴파일러는 자동적으로 더 넓은 타입으로 형변환 해준다.
즉 타입 프로모션의 규칙은 ‘기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환 해준다.’ 이다.
1차 및 2차 배열 선언하기
배열은 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것 이라고 나온다.
그리고 1차원 선언 방법은
타입[] 변수이름; //배열 선언(배열을 다루기 위한 참조변수 선언)
변수이름 = new 타입[길이]; // 배열을 생성( 실제 저장공간 생성)
2차원 선언 방법은
타입[][] 변수이름; // int[][] score;
타입[] 변수이름[]; // int[] score[];
타입 변수이름[][]; // int score[][];
초기화는 첫번째 [ ] 은 ‘행’ 이고 두번째 [] 은 ‘열’ 이다.
int[][] score = new int[4][2];
타입 추론, var
타입 추론이란, 코드 작성 당시엔 타입이 정해져 있지 않았지만, 컴파일러가 그 타입을 유추하는 것이다.
이는 곧 타입을 명시하지 않아도 되며 가독성을 높일 수 있다.
그리고 var 이거 자바스크립트에서 보던 것인데 java에서 보인다 ( 아직 난 개발자가 되려면 멀었나 보다..)
찾아보니깐 java 10 에서부터 지원하는 변수로 선언할 수 있게 되었다. 그리고 11부터 이를 이용한 람타타입 지원도 생겼다 한다. 그리고 javascript에서 var랑 비슷하면서 다른데 java에서의 var는 종속적인 강타입으로 관리하기 때문이라고 한다. 또한 var는 선언과 동시에 초기화 해줘야 한다. 나는 var 같은 경우는 클래스 타입이 제네릭으로 해서 길거나 값이 복잡해지면 var 쓰고 설명만 잘해놓으면 괜찮게 사용할 수 있다 생각한다. (근데 여긴 내 생각 쓰는데가 아닌데;;) 일단은 백기선님 스터디 들으면서 var에 대한 설명이 나오면 잘 들어봐야겠다.