본문 바로가기

코딩 국비 학원/Do it! 자바 프로그래밍 입문

[Do it! 자바 프로그래밍 입문]상수, 리터럴, 형 변환, 기본 연산자

22.12.01 배운 내용 정리
(상수, 리터럴, 형 변환, 기본 연산자)

 

상수


변수 = 변하는 수
상수 = 변하지 않는 수(ex. 원주율 3.14, 1년 12개월 등)
자바에서 상수는 final 예약어를 사용해 선언함
ex. final double PI = 3.14;
final int MAX_NUM = 100;

상수 이름은 대문자를 주로 사용하고, 여러 단어를 연결하는 경우에 _기호를 사용하면 보기 좋음
한 번 선언한 상수는 변하지 않기 때문에 선언과 동시에 값을 지정하는 것이 좋음
→ 상수는 값을 가져와서 사용할 수 있을 뿐, 한 번 대입한 값을 변경하려고 하면 오류 발생
가끔은 선언만 하고 사용하기 전에 값을 지정하기도 함

 

상수 사용하기

 

상수를 사용하면 편리한 이유


프로그램 내부에서 반복적으로 사용하고, 변하지 않아야 하는 값을 상수로 선언하여 사용하면 좋음
ex. 학급의 학생 수가 최대 30명이라는 코드를 작성하는 경우
값을 코드에 바로 사용하면 나중에 30이라는 값을 수정해야하는 일이 생길때 값 30을 쓴 부분을 모두 찾아서 변경해야함
but 상수로 선언해 사용했다면 상수를 선언한 부분의 값만 변경해주면 됨
ex. final int MAX_STUDENT_NUM = 35; // 값이 MAX_STUDENT_NUM이라면
if(count == MAX_STUDENT_NUM) { . . . } // MAX_STUDENT_NUM보다 작은 동안
while(i < MAX_STUDENT_NUM) { . . . }


리터럴


리터럴(리터럴 상수) = 프로그램에서 사용하는 모든 숫자, 문자, 논리값(true, false)을 일컫는 말
ex. char ch = 'A';
int num = 10;
final double PI = 3.14;

리터럴은 변수나 상수 값으로 대입 가능하며, 프로그램이 시작할 때 시스템에 같이 로딩되어 특정 메모리 공간인
상수 풀(constant pool)에 놓임.
ex. int num = 3; 문장에서 값 3이 메모리 공간 어딘가에 존재해야 num 변수에 그 값을 복사할 수 있음.
즉 숫자가 변수에 대입되는 과정은 일단 숫자 값이 어딘가 메모리에 쓰여 있고, 이 값이 다시 변수 메모리에 복사되는 것임

자바에서 정수를 표현하는 메모리의 기본 크기 = 4바이트 = 상수 풀에서도 마찬가지
ex. 리터럴 10 = int형(4바이트)으로 처리됨.
그러나 long num = 12,345,678,900;은 4바이트 크기에 들어갈 수 없기 때문에 리터럴 뒤에 식별자 L 또는 l을 써줘야함
실수도 마찬가지로 모든 실수 리터럴은 double형(8바이트)으로 처리됨.
그러나 float pi = 3.14;의 경우 3.14는 double형이고, 변수 pi는 float형이므로 리터럴 뒤에 식별자 F또는 f를 써줘야함


 

형 변환


정수와 실수는 컴퓨터 내부에서 표현되는 방식이 전혀 다르기 때문에
정수와 실수를 더한다고 할 때 그대로 연산을 수행할 수 없고 하나의 자료형으로 통일한 후 연산을 해야함
→ 이때 형 변환(type conversion)이 이루어짐. 즉 형 변환이란 각 변수의 자료형이 다를 때 자료형을 같게 바꾸는 것임
ex. int n = 10; //int형 변수 n에 정수 값 10을 대입
double dnum = n; //int형 변수 n의 값을 double형 변수 dnum에 대입

형변환의 기본원칙
① 바이트 크기가 작은 자료형에서 큰 자료형으로 형 변환은 자동으로 이루어짐
② 덜 정밀한 자료형에서 더 정밀한 자료형으로 형 변환은 자동으로 이루어짐

형 변환은 크게 묵시적 형 변환(자동 형 변환)명시적 형 변환(강제 형 변환) 두 가지로 구별해서 생각 가능

위 그림에서 화살표 방향과 반대로 형 변환을 하려면 강제로 변환해야 함.
long형이 8바이트이고 float형이 4바이트인데 자동 형 변환이 되는 이유 = 실수가 정수보다 표현 범위가 더 넓고 정밀함
화살표 방향으로 형 변환이 이루어질 때는 자료 손실 X but 그 반대인 경우에는 자료 손실 발생 가능

묵시적 형 변환

① 바이트 크기가 작은 자료형에서 큰 자료형으로 대입하는 경우
ex. byte bNum = 10;
int iNum = bNum; //byte형 변수 bNum 값을 int형 변수 iNum에 대입함
이 경우 bNum의 크기는 1바이트, iNum의 크기는 4바이트이므로
자료 손실 없이 bNum에 들어 있는 값이 모두 iNum에 저장됨.(남은 3바이트에는 0으로 채워짐)

② 덜 정밀한 자료형에서 더 정밀한 자료형으로 대입하는 경우
ex. int iNum2 = 20;
float fNum = iNum2;
이 경우 두 변수의 크기가 같은 4바이트라도 float형인 fNum이 더 정밀하게 데이터를 표현할 수 있으므로
실수형인 float형으로 변환됨

③ 연산 중에 자동 변환되는 경우
ex. int iNum = 20;
float fNum = iNum;
double dNum;
dNum = fNum + iNum;
이 경우 dNum = fNum + iNum에서 두 번의 형 변환 발생
→ fNum + iNum 연산에서 int형이 float형으로 변환 → 두 변수를 더한 결과 값이 dNum에 대입되면서 double형으로 변환

 

묵시적 형 변환

 

명시적 형 변환

① 바이트 크기가 큰 자료형에서 작은 자료형으로 대입하는 경우
byte형은 1바이트로 int형보다 크기가 작기 때문에 자료 손실이 발생할 수 있음.
따라서 프로그래머가 변환할 자료형을 명시적으로 써 주어야함(강제 형 변환)
ex. int iNum = 10;
byte bNum = (byte)iNum //강제로 형을 바꾸려면 바꿀 형을 괄호를 써서 명시해야 함
이 경우에는 대입된 값 10을 1바이트 안에 표현할 수 있으므로 자료 손실 X

ex. int iNum = 1000;
byte bNum = (byte)iNum;
이 경우에는 byte형이 표현할 수 있는 범위(-128~127)를 넘기 때문에 자료 손실 발생 → 대입된 값이 -24로 출력됨

② 더 정밀한 자료형에서 덜 정밀한 자료형으로 대입하는 경우
실수 자료형에서 정수 자료형으로 값이 대입되는 경우에도 역시 형 변환을 명시적으로 해주어야 함
ex. double dNum = 3.14;
int iNum2 = (int)dNum; //실수 자료형 double을 정수 자료형 int로 형 변환
이 경우에는 실수의 소수점 이하 부분이 생략되고 정수 부분만 대입됨 → 대입된 값이 3으로 출력됨

③ 연산 중 형 변환

명시적 형 변환(연산 중 형 변환)

8행, 9행 연산 결과 다름
8행 : 두 실수가 각각 명시적으로 형 변환이 일어남. 따라서 1과 0으로 변환된 두 값을 합하여 결과 값이 1이 됨
9행 : 두 dNum1과 fNum2의 합을 먼저 계산함. 이때 두 실수의 자료형이 다르지만, float형이 double형으로 변환되는
묵시적 형 변환이 일어나면서 두 수가 더해져 결과값이 2.1이 되고, 이후에 int형으로 명시적 형 변환이 되어
결과 값이 2가 됨.
이처럼 같은 연산이라도 형 변환이 언제 이루어졌는지에 따라 그 결과 값이 다르게 나타날 수 있음.


2장 연습문제 풀이

① 바이트 크기가 작은 자료형을 더 큰 자료형으로 대입하는 형 변환은 자동으로 이루어진다 = (O)

형변환의 기본원칙
▶ 바이트 크기가 작은 자료형에서 큰 자료형으로 형 변환은 자동으로 이루어짐
▶ 덜 정밀한 자료형에서 더 정밀한 자료형으로 형 변환은 자동으로 이루어짐


② 실수를 정수형 변수에 대입하는 경우에 형 변환이 자동으로 이루어지고, 소수점 이하 부분만 없어진다 = (X)

실수 자료형에서 정수 자료형으로 값이 대입되는 경우 형 변환을 명시적으로 해주어야 함
ex. double dNum = 3.14;
int iNum2 = (int)dNum; //실수 자료형 double을 정수 자료형 int로 형 변환
이 경우에는 실수의 소수점 이하 부분이 생략되고 정수 부분만 대입됨 → 대입된 값이 3으로 출력됨


③ 더 많은 실수를 표현하기 위해 가수부와 지수부로 비트를 나누어 표현하는 방식 = 부동소수점형

④ 변수 두 개를 선언해서 10과 2.0을 대입하고 두 변수의 사칙 연산 결과를 정수로 출력하기

 


두 변수의 사칙 연산 수행시 실수형으로 나옴
→ 정수로 출력하기 위해 명시적 형 변환 필요
→ 따라서 실수형 변수(y)에 (int)를 써줘야 함

⑤ '글'이라는 *한글 문자의 유니코드 값을 찾아서 char형으로 선언한 변수에 저장한 뒤 그 변수를 출력하여 확인해보기
*www.unicode.org/charts/PDF/UAC00.pdf 사이트 참고

 


'글' 한글 문자 유니코드 값 = \uAE00


항과 연산자


연산자(operator) = 연산에 사용하는 기호(ex. +, - 등)
항(operand) = 연산에 사용하는 값(ex. 1, 2, 3, 4 ...등)

연산자는 항의 개수에 따라 ①단항 연산자(항이 1개), ②이항 연산자(항이 2개), ③삼항 연산자(항이 3개)로 나눌 수 있음

연산자 설명 연산 예
단항 연산자 항이 한 개인 연산자 ++num
이항 연산자 항이 두 개인 연산자 num1 + num2;(사칙연산)
삼항 연산자 항이 세 개인 연산자 (5 > 3) ? 1 : 0;


연산자 우선순위 = 연산 순서(ex. 사칙 연산 할 때 곱셈과 나눗셈을 덧셈과 뺄셈보다 우선 계산)
프로그램에 사용하는 연산자도 우선순위 존재 = 단항 연산자 > 이항 연산자 > 삼항 연산자

대입 연산자


대입 연산자(assignment operator) = 변수에 값을 대입하는 연산자(=)
대입 연산자는 이항 연산자 중 우선순위가 가장 낮음
대입 연산자는 오른쪽 변수 값이나 식의 연산 결과 값을 왼쪽 변수에 대입함
ex. int age = 24; //나이를 의미하는 age 변수에 값 24 대입 = 오른쪽 변수(24)값을 왼쪽 변수(int)에 대입
ex. totalScore = mathScore + engScore; //① mathScore + engScore 우선 수행 ② +한 값을 totalScore에 대입

 

※ 왼쪽 변수(lValue)와 오른쪽 변수(rValue)

대입 연산자(=)를 기준으로 왼쪽에 있는 변수를 lvalue(left value), 오른쪽에 있는 변수를 rValue(right value)라고 함
대입 연산자를 사용하면 항상 오른쪽 변수 값을 가져와서 왼쪽 변수에 대입하는 것을 알 수 있음
따라서 값이 대입되는 왼쪽 변수에는 10같은 숫자가 올 수 없고 항상 변수나 상수가 와야함
오른쪽 변수에는 변수나 숫자(상수)가 올 수 있음

 

부호 연산자


부호 연산자는 +, - 두 가지가 있음.
더하기, 빼기 연산에 쓰는 이항 연산자이면서 부호를 나타내는 단항 연산자로도 사용
ex. +3(=양수), -3(=음수)

연산자 기능 연산 예
+ 변수나 상수 값을 양수로 만듦 +3
- 변수나 상수 값을 음수로 만듦 -3


그런데 변수에 - 연산자만 사용한다고 해서 값 자체가 음수로 바뀌는 것은 아님
앞 코드에서 값 자체를 음수로 바꾸려면 = 연산자(대입 연산자)를 사용하여 값을 대입해야 함.
따라서 num = -num의 결과 값은 음수가 됨 (아래 그림 참조)

 

 

산술 연산자


산술 연산자 = 덧셈( + ), 뺄셈( - ), 곱셈( * ), 나눗셈( / ), 나머지(%) → 사칙 연산에서 사용하는 연산자
※ 프로그래밍 할때 곱셈 기호는 X 가 아닌 * 을 사용하며, 나눗셈 기호는 ÷ 대신 / 를 사용함

 

연산자 기능 연산 예
+ 두 항을 더함 5 + 3
- 앞에 있는 항에서 뒤에 있는 항을 뺌 5 - 3
* 두 항을 곱함 5 * 3
/ 앞에 있는 항에서 뒤에 있는 항을 나누어 몫을 구함 5 / 3
% 앞에 있는 항에서 뒤에 있는 항을 나누어 나머지를 구함 5 % 3


산술 연산자의 우선순위 = 일반 수학의 산술 연산과 같음. 나머지( % )의 우선 순위는 곱셈( * ), 나눗셈( / )과 동일함

 

산술 연산자를 사용하여 총점과 평균 구하기

 

증가·감소 연산자


증가·감소 연산자 = 단항 연산자로 연산자 앞이나 뒤에 사용하며 값을 1만큼 늘리거나 1만큼 줄임

 

연산자 기능 연산 예
++ 항의 값에 1을 더함 val = ++num; //먼저 num 값이 1 증가한 후 val 변수에 대입
val = num++; //val 변수에 기존 num 값을 먼저 대입한 후 num 값 1 증가
-- 항의 값에서 1을 뺌 val = --num; //먼저 num 값이 1 감소한 후 val 변수에 대입
val = num--; //val 변수에 기존 num 값을 먼저 대입한 후 num 값 1 감소

 

※ 증가·감소 연산자의 위치

연산자를 피연산자 앞에 쓰는 경우와 뒤에 쓰는 경우 그 결과 값이 전혀 다르므로 주의해야 함
프로그램에서 한 문장은 우리말에서 하나의 문장과 의미가 같다고 생각하면됨
한글에서 문장의 끝에는 .(마침표)사용 → 자바 프로그램에서는 문장 끝에 ;(세미콜론)사용
;(세미콜론)까지가 하나의 문장이라고 할 수 있음.

증가·감소 연산자가 피연산자 앞에 있으면 문장이 나기 전에 피연산자 값이 증가하거나 감소하고(전위증가, 감소)
반대로 증가·감소 연산자가 피연산자 뒤에 있으면 문장이 끝난 후에 피연산자 값이 증가하거나 감소함(후위증가, 감소)
ex. int value = 10;
int num = ++value; //num에 11이 대입됨(전위증가)
ex. int value = 10;
int num = value++; //num에 10이 대입됨(후위증가)

 

증감 연산자

 

관계 연산자

 

관계 연산자 = 이항 연산자로 두 개의 항 중 어느 것이 더 큰지, 작은지, 같은지 등의 여부를 검사함(ex. 부등호)

관계 연산자의 결과 값은 참(true) 또는 거짓(false)으로 반환됨

 

ex. 다음과 같은 경우 value 값은 참이 되어 true 값을 가지게 됨

int myAge = 27;

boolean value = *(myAge > 25);

System.out.println(value);    //true

 

*(myAge > 25)에서 괄호를 사용한 이유 = 가독성이 좋은 코드를 만들기 위해

 

연산자 기능 연산 예
> 왼쪽 항이 크면 참, 아니면 거짓 반환 num > 3;
< 왼쪽 항이 작으면 참, 아니면 거짓 반환 num < 3;
>= 왼쪽 항이 오른쪽 항보다 크거나 같으면 참, 아니면 거짓 반환 num >= 3;
<= 왼쪽 항이 오른쪽 항보다 작거나 같으면 참, 아니면 거짓 반환 num <= 3;
== 두 개 항의 값이 같으면 참, 아니면 거짓 반환 num == 3;
!= 두 개 항이 다르면 참, 아니면 거짓 반환 num != 3;

 

논리 연산자

 

논리 연산자 = 명제라고 생각하면 됨.

두 명제가 모두 참이면 논리 곱은 참, 두  명제 중 하나만 참이면 논리 합은 참, 참의 부정은 거짓, 거짓의 부정은 참

 

논리 연산자는 주로 관계 연산자와 함께 사용하며, 관계 연산자의 우선순위가 논리 연산자보다 높으므로(관계 > 논리),

관계 연산자의 결과 값을 기반으로 논리 연산자의 결과 값을 계산함

 

연산자 기능 연산 예
&&
(논리 곱)
두 항이 모두 참인 경우에만 참, 아니면 거짓 반환 boolean val =
(5 > 3) && (5 > 2);
||
(논리 합)
두 항 중 하나의 항만 참이면 참, 두 항 모두 거짓이면 거짓 boolean val =
(5 > 3) II (5 > 2);
!
(부정)
단항 연산자로 참인 경우엔 거짓으로, 거짓인 경우는 참으로 바꿈 boolean val = !(5 > 3);

 

※ ||(논리 합) 적는 법 = Shift + \(역슬래쉬)

 

단락 회로 평가(SCE : short Circuit Evaluation) = 논리 곱 연산과 논리 합 연산을 할 때 두 항을 모두 실행하지 않더라도

결과 값을 알 수 있는 경우에, 나머지 항은 실행되지 않는 것

 

단락 회로 평가

 

복합 대입 연산자

 

복합 대입 연산자 = 대입 연산자와 다른 연산자를 조합해 하나의 연산자처럼 사용하는 연산자로,

산술 연산자, 비트 연산자와 함께 사용하여 코드를 간결하게 표현 가능

 

대입 연산자는 우선순위가 가장 낮은 연산자이므로

복합 대입 연산자 역시 연산이 모두 끝난 후 마지막으로 결과 값을 변수에 대입함

연산자 기능 연산 예
+= 두 항의 값을 더해서 왼쪽 항에 대입 num1 += 2;
num1 = num1 + 2;와 같음
-= 왼쪽 항에서 오른쪽 항을 빼서 그 값을 왼쪽 항에 대입 num1 -= 2;
num1 = num1 - 2;와 같음
*= 두 항의 값을 곱해서 왼쪽 항에 대입 num1 *= 2;
num1 = num1 * 2;와 같음
/= 왼쪽 항을 오른쪽 항으로 나누어 그 몫을 왼쪽 항에 대입 num1 /= 2;
num1 = num1 / 2;와 같음
%= 왼쪽 항을 오른쪽 항으로 나누어 그 나머지를 왼쪽 항에  대입 num1 %= 2;
num1 = num1 % 2;와 같음
<<= 비트를 왼쪽으로 이동하고 그 값을 왼쪽 항에 대입 num1 <<= 2;
num1 = num1 << 2;와 같음
>>= 비트를 오른쪽으로 이동하고 그 값을 왼쪽 항에 대입
(왼쪽에 채워지는 비트 값은 부호 비트와 동일)
num1 >>= 2;
num1 = num1 >> 2;와 같음
>>>= 비트를 오른쪽으로 이동하고 그 값을 왼쪽 항에 대입
(왼쪽에 채워지는 비트 값은 0)
num1 >>>= 2;
num1 = num1 >>> 2;와 같음
&= 두 항의 & 비트 연산 후 그 값을 왼쪽 항에 대입 num1 &= num2;
num1 = num1 & num2;와 같음
|= 두 항의 | 비트 연산 후 그 값을 왼쪽 항에 대입 num1 |= num2;
num1 = num1 | num2;와 같음
^= 두 항의 ^ 비트 연산 후 그 값을 왼쪽 항에 대입 num1 ^= num2;
num1 = num1 ^ num2;와 같음

 

조건 연산자

 

조건 연산자 = 삼항 연산자로 주어진 조건식이 참인 경우와 거짓인 경우에 다른 결과 값이 나옴

 

연산자 기능 연산 예
조건식 ? 결과 1 : 결과2; 조건식이 참이면 결과1,
조건식이 거짓이면 결과2가 선택됨
Int num = (5 > 3) ? 10 : 20;
→ 5가 3보다 크므로 조건식이 참.
따라서 num값은 10이 됨

 

조건 연산자

 

※ 조건 연산자를 사용하여 10이 짝수인 경우에는 T, 그렇지 않으면 F를 출력

int num = 10;

boolean isEven;

isEven = (num % 2) == 0 ? true : false;   //(num % 2) == 0는 2로나누었을 때 0이 되는 지의 의미(짝수인지)

System.out.println(isEven);

→ true 출력