Chapter 2-2 변수의 타입

HeeSeong·2021년 5월 11일
0

Java

목록 보기
2/3
post-thumbnail

1. 변수의 타입

값의 종류에 따라 값이 저장될 공간의 크기와 저장형식을 정의한 것이 자료형이다.
변수를 선언할 때에 저장하려는 값의 특성을 고려하여 가장 알맞은 자료형을 변수의 타입으로 선택하면 된다.


2. 기본형과 참조형

자료형(Data Typr)은 크게 기본형과 참조형 두가지로 나눌 수 있다.

  • 기본형 : 실제 값을 저장한다.
    논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float, double)

  • 참조형 : 값이 저장되어 있는 주소를 값으로 갖는다.

자바는 참조형 변수 간의 연산을 할 수 없으므로 실제 연산에 사용되는 것은 기본형 변수이다. 참조변수의 타입은 클래스의 이름이다.


참조변수는 null 또는 객체의 주소를 값으로 가지며 초기화는 다음과 같이 한다.

Date today = new Date();

연산자 new의 결과는 생성된 객체의 주소이다. 이 주소가 대입연산자에 의해서 참조변수 today에 저장되는 것이다.


2-1 기본형(Primitive Type)


java에서 기본 데이터 타입이란 정수, 실수, 문자, 논리 리터럴을 직접 저장하는 타입을 말한다.
문자형인 char은 문자를 내부적으로 정수(유니코드)로 저장하기 때문에 정수형과 별반 다르지 않으며, 정수형 또는 실수형과 연산도 가능하다. 반면 boolean은 다른 기본형과의 연산이 불가능하고 나머지 7개의 기본형은 서로 연산과 변환이 가능하다.

정수는 타입을 4가지 제공하며 각 타입마다 저장할 수 있는 값의 범위가 다르다.
일반적으로 int는 CPU가 가장 효율적으로 처리할 수 있는 타입이기 때문에 많이 사용한다.
효율적인 실행보다 메모리를 절약하려면 byte나 short를 선택한다.


2-2 참조형(Reference Type)


java에서 참조 타입(reference type)이란 객체의 번지를 참조하는 타입으로 배열, 열거, 클래스, 인터페이스 타입을 말한다.
기본 타입으로 선언된 변수와 참조 타입으로 선언된 변수의 차이점은 저장되는 값이 무엇인가의 차이이다. 기본 타입으로 선언된 변수는 실제 값을 변수 안에 저장하지만 참조 타입으로 선언된 변수는 메모리의 번지를 값으로 갖는다. 번지를 통해 객체를 참조한다는 뜻에서 참조타입이라고 부른다.

변수는 스택 영역에 생성되고 객체는 힙 영역에 생성된다.


3. 상수와 리터럴

상수(constant)는 변수와 마찬가지로 '값을 저장할 수 있는 공간'이지만, 변수와 달리 한번 값을 저장하면 다른 값으로 변경할 수 없다.

final int MAX_SPEED = 10;

상수는 반드시 선언과 동시에 초기화하는 것이 권장되며, 상수의 값을 변경하는 것이 허용되지 않는다.
상수의 이름은 모두 대문자로 하는 것이 관례이며, 여러 단어로 이루어져있는 경우 '_'로 구분한다.


프로그래밍에서는 상수를 '값을 한 번 저장하면 변경할 수 없는 저장공간'으로 정의하였기 때문에 구분하기 위해 상수를 '리터럴'이라는 용어로 부른다. 상수는 코드의 이해와 수정을 쉽게 만든다.

  • 변수 : 하나의 값을 저장하기 위한 공간
  • 상수 : 값을 한번만 저장할 수 있는 공간
  • 리터럴 : 그 자체로 값을 의미하는 것(대입연산자 오른쪽의 값)

3-1 리터럴의 타입과 접미사

정수형과 실수형에는 여러 타입이 존재하므로, 리터럴에 접미사를 붙여서 타입을 구분한다. 정수형의 경우, long 타입의 리터럴에 접미사 'l' 또는 'L'을 붙이고, 접미사가 없으면 int 타입의 리터럴이다. byte, short 타입의 리터럴은 별도로 존재하지 않으며 byte, short 타입의 변수에 값을 저장할 때는 int 타입의 리터럴을 사용한다.


10진수 외에도 2, 8, 16진수로 표현된 리터럴을 변수에 저장할 수 있으며, 16진수라는 것을 표시하기 위해 리터럴 앞에 접두사 '0x' 또는 '0X'를, 8진수의 경우에는 '0'를 붙인다.

int octNum = 010;  // 8진수 10
int hexNum = 0x10; // 16진수 10
int binNum = 0b10; // 2진수 10

JDK 1.7부터 정수형 리터럴의 중간에 구분자 '_'를 넣을 수 있게 되어서 큰 숫자를 편하게 읽을 수 있게 되었다.

long big = 100_000_000_000L;  // long big = 100000000000L;
long hex = 0xFFFF_FFFF_FFFF_FFFFL;  // long hex = 0xFFFFFFFFFFFFFFFFL;

실수형에서는 float 타입의 리터럴에 접미사 'f' 또는 'F'를 붙이고, double 타입의 리터럴에는 접미사 'd' 또는 'D'를 붙인다.

float pi = 3.14f;
double rate = 1.618d;

실수형 리터럴은 double이 기본 자료형이다. 접미사 'd'는 생략이 가능하고 접미사가 없으면 double 타입 리터럴이다.

float pi = 3.14;  // 에러 발생, float 타입 변수에 double 타입 리터럴 저장 불가능
double rate = 1.618;  // 정상, 접미사 d는 생략 가능

리터럴에 접미사가 붙는 타입은 long, float, double 뿐인데, double은 생략 가능하므로
long과 float의 리터럴에 접미사를 붙이는 것만 신경쓰면 된다.

리터럴에 소수점이나 10의 제곱을 나타내는 기호 E, e 그리고 접미사 f, F, d, D를 포함하고 있으면 실수형 리터럴로 간주된다.


4. 타입의 불일치

리터럴의 타입은 저장될 변수의 타입과 일치하는 것이 보통이지만, 타입이 달라도 저장 범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다.

int i = 'A';  // 정상. 문자 'A'의 유니코드인 65가 변수에 저장된다
long l = 123;  // 정상. int보다 long의 범위가 더 크다
double d = 3.14f;  // 정상. float보다 double의 범위가 더 크다

그러나 리터럴의 값이 변수의 타입의 범위를 넘어서거나, 리터럴의 타입이 변수의 타입보다 저장범위가 넓으면 컴파일 에러가 발생한다.

int i = 0x123456789;  // 에러. int 타입의 범위를 넘는 값
float f = 3.14;  // 에러. float 타입보다 double 타입의 범위가 넓다

byte와 short 타입의 리터럴은 따로 존재하지 않고 int 타입의 리터럴을 사용한다. 단, short 타입의 변수가 저장할 수 있는 범위에 속한 것이어야 한다.

byte b = 65;  // 정상
short s = 0x1234;  // 정상

5. 문자 리터럴 & 문자열 리터럴

  • 문자 리터럴 : 작은 따옴표로 문자 하나를 감싼 것

  • 문자열 리터럴 : 큰 따옴표로 두 문자 이상을 감싼 것


char 타입의 변수는 단 하나의 문자만 저장할 수 있으므로, 여러 문자를 저장하기 위해서는 String 타입을 사용해야 한다.

char ch = 'J';
String name = "Java";

문자열 리터럴은 ""안에 아무런 문자도 넣지 않는 것을 허용하며, 이를 빈 문자열이라고 한다.
그러나 문자 리터럴은 ""안에 반드시 하나의 문자가 있어야 한다.

// 원래 String은 클래스라 1번째 줄처럼 연산자 new를 사용해야 하지만 2번째 줄과 같은 표현도 허용
String name = new String("Java");  
String str = "";  // 정상. 내용이 없는 빈 문자열
char ch = '';  // 에러. 빈 문자 불가능
char ch2 = ' ';  // 정상. 공백 문자로 변수 초기화

덧셈 연산자를 이용하여 문자열을 결합할 수 있다.
덧셈 연산자(+)는 피연산자가 모두 숫자일 때는 두 수를 더하지만, 피연산자 중 어느 한쪽이 String이면 나머지 한 쪽을 먼저 String으로 변환한 다음 두 String을 결합한다.
기본형, 참조형의 구별 없이 어떤 타입의 변수도 문자열과 덧셈 연산을 수행하면 결과가 문자열이 된다.

String name = "ja" + "va";  // "Java"
String str = name + 8.0;  // "Java8.0"

7 + " "  // "7 "
7 + "7"  // "77"
7 + 7 + ""  // "14"
true + ""  // "true"

6. 형식화된 출력 - printf()

화면에 출력할 때 println()을 써왔는데, 사용하기엔 편하지만 변수의 값을 그대로 출력하므로, 값을 변환하지 않고는 다른 형식으로 출력할 수 없다. 같은 값이라도 다른 형식으로 출력하고 싶을 때 printf()를 사용하면 된다.

printf()는 지시자를 통해 변수의 값을 여러 가지 형식으로 변환하여 출력하는 기능을 가지고 있다. 지시자는 값을 어떻게 출력할 것인지 지정해주는 역할을 한다.
정수형 변수에 저장된 값을 10진 정수로 출력할 때는 지시자 '%d'를 사용하며, 변수의 값을 지정된 형식으로 변환해서 지시자 대신 넣는다.

만일 출력하려는 값이 2개라면, 지시자도 2개를 사용해야하며 출력될 값과 지시자의 순서는 일치해야 한다.

int age = 14;
int year = 2017;
System.out.printf("age:%d", age);  // "age:14"
System.out.printf("age:%d year:%d", age, year);  // "age:14 year:2017"


6-1 예제

정수룰 출력할 때는 지시자 '%d'를 사용하는데, 출력될 값이 차지할 공간을 숫자로 지정할 수 있다. (%n은 출력 줄바꿈)

int finger = 10;
long hex = 0xFFFF_FFFF_FFFF_FFFFL;

System.out.printf("finger = [%5d]%n", finger);  // finger = [   10]
System.out.printf("finger = [%-5d]%n", finger);  // finger = [10   ]
System.out.printf("finger = [%05d]%n", finger);  // finger = [00010]

지시자 '%x'와 '%o'에 '#'를 사용하면 접두사 '0x'와 '0'이 각각 붙는다. 그리고 '%X'는 16진수에 사용되는 접두사와 영문자를 대문자로 출력한다.

System.out.printf("hex = %x%n", hex);  // hex = ffffffffffffffff
System.out.printf("hex = %#x%n", hex);  // hex = 0xffffffffffffffff
System.out.printf("hex = %#X%n", hex);  // hex = 0Xffffffffffffffff

10진수를 2진수로 출력해주는 지시자는 없기 때문에, 정수를 2진 문자열로 변환해주는 'Integer.toBinaryString(int i)'를 사용해야 한다.

그리고 자바에서는 char 타입의 값을 지시자 '%d'로 출력이 허용되지 않아 int 타입으로 형변환 해야 '%d'로 출력할 수 있다.

char c = 'A';
int binNum = 0b10;

System.out.printf("binNum = %s%n", Integer.toBinaryString(binNum));  // binNum = 10
System.out.printf("c = %c, %d %n", c, (int)c);  // c = A, 65

실수형 값의 출력에 사용되는 지시자는 '%f', '%e', '%g'가 있는데, '%f'가 주로 쓰이고, '%e'는 지수형태 출력할 때, '%g'는 값을 간략하게 표현할 때 사용한다.

'%f'는 기본적으로 소수점 아래 6자리까지만 출력해서 소수점 아래 7자리에서 반올림한다.
그리고 다음과 같이 전체 자리 수와 소수점 아래의 자리수를 지정할 수도 있다.
소수점도 한자리를 차지하며, 소수점 아래의 빈자리는 0으로 채우고 정수의 빈자리는 공백으로 채워서 전체 자릿수를 맞춘다.

double d = 1.23456789;

// %전체자리.소수점 아래자리f
System.out.printf("d = %14.10f%n", d);  // [  1.2345678900] 전체 14자리 중 소수점 아래는 10자리
System.out.printf("d = %014.10f%n", d);  // [001.2345678900]

지시자 '%s'에도 숫자를 추가하면 원하는 만큼의 출력공간을 확보하거나 문자열의 일부만 출력할 수 있다.

String url = "www.code.com";

System.out.printf("[%s]%n", url);  // [www.code.com] 문자열 길이만큼 출력공간
System.out.printf("[%20s]%n", url);  // [        www.code.com] 우측정렬. 최소 20글자 출력공간
System.out.printf("[%-20s]%n", url);  // [www.code.com        ] 좌측정렬. 최소 20글자 출력공간
System.out.printf("[%.8s]%n", url);  // [www.code] 왼쪽에서 8글자만 출력

7. 화면에서 입력받기 - Scanner

자바에서 화면으로부터 입력받는 방법 중 하나이다.

import java.util.*;

Scanner scanner = new Scanner(System.in);  // Scanner 클래스의 객체 생성

// nextLine() 호출하면 입력대기 상태에 있다가 입력을 마치고 Enter를 누르면 입력한 내용이 문자열로 반환된다.
String input = scanner.nextLine();
int num = Integer.parseInt(input); // 입력받은 내용을 int 타입 값으로 변환

Scanner 클래스에는 nextInt()나 nextFloat() 같이 변환 없이 숫자로 바로 입력받을 수 있는 메서드들이 있지만 이것들은 화면에서 연속적으로 값을 입력받아서 사용하기에 까다롭다. 모든 값을 nextLine()으로 입력받아서 적절히 변환하는 것을 추천한다.

profile
끊임없이 성장하고 싶은 개발자

0개의 댓글