본문 바로가기

프로그래밍 언어 기초/JAVA

chapter 2. 연산자(Operator)

 

 친구들과 놀러가기 위해 멋진 여행 계획을 세우고, 그 다음으로 키게 되는 것! 바로 여행 비용은 얼마나 될까 계산기를 두들겨보게 되죠. 학창시절 학교에서 졸린 눈 비비며 배웠던 더하기, 빼기, 곱하기, 나누기... 수학 선생님이 내주신 숙제 한 번 하려고 한다면 문구점에서 구매한 공책을 펴고 예쁘게 깎은 연필로 수학식을 써가며 어렵사리 계산해 갑니다. 아, 이거 누가 대신 안해주나 귀찮은 마음이 들기도 했었는데 그래서 준비했습니다! 우리의 든든한 친구 컴퓨터는 우리가 힘들게 수식을 작성하며 계산할 일을 1초에 1억번을 할 수 있는 아주 멋진 성능을 갖추었답니다. 오늘은 어떻게 우리의 지원군 컴퓨터에게 우리를 대산하여 귀찮은 계산들을 부탁할지 알아보도록 하겠습니다.

 

 

2. 연산자란?

 자바에는 다양한 값들을 저장할 수 있는 만능 상자! 컴퓨터의 메모리의 공간을 차지하는 "변수"라는 것이 있었죠. 만약 이 변수라는 것이 단순히 저장하고 꺼내는 것에 지나지 않았다면, 변수의 가치는 높지 않았을지도 모르겠습니다. 연산자란 이러한 변수나 primitive type 자료형처럼 실제 값 자체 등을 통해 새로운 결과를 도출해낼 수 있는 약속된 기호라고 할 수 있는데요. 쉽게 말해서 우리가 '이러한 이름을 갖는 변수에는 이 값을 넣을거야'라고 작성한 코드 한줄도 사실은 연산자가 있었기에 가능했던 것이었습니다.

 

 

 

2.1. 연산의 종류

 프로그래밍 언어에서는 앞서 더하기, 빼기, 곱하기, 나누기 처럼 수학적인 "계산" 뿐만 아니라 '이 변수에는 이 값을 넣을거야' 라고 직접 작성한 코드 한줄도 연산이라고 볼 수 있습니다. 이처럼 우리는 정말 자연스럽게 또 다양하게 프로그래밍 언어에서 다양한 연산들을 수행하고 있었고 수행할 수 있는데, 오늘은 이러한 연산에 대해서 알아보도록 하겠습니다.

 

2.1.1. 산술연산

수학에서 사칙연산이라고 정의하는 수학적 계산을 수행할 수 있는 연산입니다. 대표적으로 +, -, /(나누기), *(곱하기) 가 있습니다. 그런데 여기서 주의할 것은 사람이 손으로 나눗셈을 할 때에는 소수점까지 구하거나, 나눗셈과 몫을 한번에 구할 수 있지만 프로그래밍 언어에서의 나눗셈은 몫만 구하는 계산을 기본으로 한다는 점입니다. 연산식을 조금 수정하거나 다른 연산자를 추가하면 사람이 나눗셈을 하듯이 계산시킬 수 있지만, JAVA에서는 기본적으로 나눗셈은 몫을 구하는 연산을 한다는 점을 꼭 기억해두어야겠습니다.

 

연산자 설명 예시 결과
+ 두 값에 대한 덧셈 연산을 수행 1 + 2  3
- 두 값에 대한 뺄셈 연산을 수행 3 - 1 2
* 두 값에 대한 곱셈 연산을 수행 3 * 2 6
/ 두 값에 대한 나눗셈(몫)연산을 수행 5 / 2 2
% 두 값에 대한 나머지 연산을 수행 5 % 2 1

 

2.1.2. 대입연산

변수에 값을 부여하는 연산을 하는 연산자입니다.

 

int intValue = 13;

 

참 쉽죠?

 

2.1.3. 비교 연산

'1013보다 작아', '배는 사과보다 커' 와 같은 비교가 필요한 연산이 필요할 때 사용 가능한 연산자입니다.

연산자 예시 설명 결과
> A > B A는 B보다 크다 true/false
< A < B A는 B보다 작다 true/false
>= A >= B A는 B보다 크거나 같다. true/false
<= A <= B A는 B보다 작거나 같다. true/false

비교연산자는 연산의 결과 값의 참 거짓에 따라 boolean으로 연산한다는 특징이 있습니다.

비교 결과가 참이면 true, 거짓이면 false 로 연산한다는 뜻이죠.

 

10 > 13 // false
13 > 10 // true

 

2.1.4. 논리 연산

자료형 Boolean과 밀접한 연관이 있는 연산자입니다. 두 값이 같다면 참 두 값이 다르다면 거짓을 판단해주세요 등의 연산이 필요할 때 사용하는 연산자입니다.

 

연산자 예시 설명 결과
== true == true 두 값이 서로 같은 지 판단 true
!= true != true 두 값이 서로 같지 않은지 판단 false

 

🔑 여기서 잠깐!     자바 프로그램이 어떻게 두 값이 같고 다른지 판단하나요?

 Java에서는 모든 프로그램 코드를 실행시켜주는 JVM(Java Virtual Machine)이란 것이 존재합니다. 자바 코드로 작성된 모든 프로그램은 운영체제로부터 JVM을 통해 최종적으로 프로그램이 동작할 수 있도록 메모리를 할당받게 되는데요. 컴퓨터의 메모리는 무한한 자원이 아니기 때문에 적절한 관리가 필요하고, 자바에서는 크게 데이터의 타입, 즉 자료형에 따라 메모리를 관리하게 됩니다. 앞서 우리가 primitive type으로 분류한 변수들은 메모리의 stack 영역에 '값=변수'의 형태로 곧바로 저장되게 되는데요. 반면에 reference type인 변수들은 stack 영역에 변수의 이름에 대한 정보가 저장되고, 실제 값이 저장된 주소 값은 heap 영역에 저장되어 호출이 될때마다 동적으로 할당을 받게 됩니다. 따라서 여기서 저장된 '주소' 값을 기준으로 논리 연산자는 같고 다름을 판단할 수 있는 것입니다, 따라서 primitive type 변수들은 그 값이 서로 같으면 true, 다르면 false로 연산하지만,  reference type은 실제 값을 조작하더라도 가리키는 주소값이 같으면 true, 주소값이 다르면 false로 판단하게 됩니다.

 

 

2.1.5. 타입 연산

타입 연산은 변수의 타입(자료형)을 다른 타입으로 변환하는 연산입니다. 기본적으로 형 변환은 primitive는 primitive끼리 reference는 reference 끼리 형 변환이 가능합니다. 단, boolean은 다른 primitive type 과 호환되지 않습니다. 그러나 

primitive 과 reference 간의 형변환이 완전히 불가한 것은 아니고 Wrapper 클래스를 통해 형 변환이 일부 가능합니다.

// wrapper 클래스를 사용한 형변환
    
String x1 = "이 값은 숫자로 뭐지?";
int x2 = Integer.parseInt(x1); // 오류 발생!!
		
String x3 = "1";
int x4 = Integer.parseInt(x3); // 3;

 

 

 타입 연산에서 유심히 보아야할 자료형은  primitive type 입니다. 그 중 특히 숫자형 타입은 형변환을 할 때 묵시적 형변환과 명시적 형변환이 있다는 특징이 있습니다. 여기서 묵시적 형변환은 범위가 작은 변수에서 큰 범위로 변환할 때 자동으로 발생하는 형변환입니다. 가령 short 타입의 변수를 int 타입으로 변환 시킬 경우 별도의 형변환 연산자를 사용하지 않아도 JVM이 이를 인식하여 자동으로 형 변환을 해줍니다. 이것이 가능한 이유는 묵시적 형변환은 반드시 자료형이 작은 타입에서 큰 타입으로 변환하는 것이기 때문에 데이터의 손실이 없기 때문입니다. 물론 묵시적 형변환이 가능한 상황이라도 개발자가 직접 형변환 연산자를 사용하여 형변환을 할 수 있습니다. 정리하자면 묵시적 형 변환은 값의 크기, 타입의 크기가 아니라 표현의 크기가 커지는 방향으로 할당할 경우 묵시적 형 변환이 발생합니다.

 

묵시적 형 변환의 순서도

 

 

 반면에 반대의 경우, 즉 값의 범위가 큰 경우에서 작은 경우로 변환할 경우 값의 손실이 발생할 수 있으므로 개발자 책임 하에 형변환을 해야 합니다. 이를 명시적 형변환이라고 합니다. 예컨데 int 형의 범위를 초과하는 값을 담던 long형 변수를 int 형으로 강제로 형변환을 하면 값의 손실이 되어 원래의 값이 손상될 수 있습니다. 또한 float형 데이터를 int형으로 변환할 경우 소수점아래의 데이터가 없어지는 등의 데이터의 손실이 생길 수 있으니 항상 명시적 형변환을 하는 경우 형변환이 가능한지, 값의 손실이 있진 않을지 꼼꼼히 확인해야겠습니다.


이처럼 자바에는 다양한 연산자가 있습니다. 수학의 산술 연산에도 우선순위가 있듯이 자바에도 연산자의 우선순위가 존재합니다. 자바의 연산자의 우선순위에 대한 순서는 아래의 표를 참고해주세요!

 

 

산술 연산자의 우선순위와 결합 방향

연산자 *결합방향 우선순위
(),   . 제일 먼저
++,   --,   +,   -,   ~,   !,   (type) 형변환  
*,   /,   %  
+  ,   -  
<<  . >>  ,   >>>  
<,   >,   <=,   >=,   instanceof  
==, !=  
&  
^  
|  
&&  
||  
? :  
=, *=, /=, %=, +=, -=, <<=, >>>=, &=, ^=, |= <- 제일 늦게

* 결합방향 : 연산의 결과가 실제로 반영되는 변수의 위치, 방향이 ← 일 경우 연산의 결과는 왼쪽에 작성한 변수에 반영.