다시 초심으로 돌아가 자바의 기초부터 깊게 공부해보자는 생각으로 연산자를 공부했다.
사실 제일 기초가 되는 문법이자 중요한 내용이나, 자세히 보지 않고 대충 넘긴 적이 많다.
처음부터 공부한다는 것에 의아할 수 있겠으나, 아직은 공부하기 여유로운 기간이기 때문에 이참에
자바에 대해 깊게 파볼 생각이다.
물론 현재 Spring 강좌를 듣고 있고, DB 등을 병행하여 공부하고 있지만 자바가 가장 중요하다고 생각했다.
모든 내용을 기술하진 않을 예정이다. 단지 내가 공부하여 새로 알게 된 내용이나 중요하다고 생각되는 내용
위주로 작성할 것이다.
1️⃣ Operator & Expressions
- 연산 (Opration) : 프로그램에서 데이터를 처리하여 결과를 산출하는 것
- 연산자 (Operator) : 연산에 사용되는 표시나 기호
- 피연산자 (Operand) : 연산되는 데이터
- 연산식 (Expressions) : 연산자, 피연산자를 통해 연산의 과정을 기술하는 것
연산자의 종류는 매우 많다. 산술, 부호, 문자열, 대입, 증감, 비교, 논리, 조건, 비트, 쉬프트 등 이 있다.
각 상황에 맞게 연산자를 선택하는 것이 중요하다. => 각 연산식은 반드시 하나의 값을 산출한다.
1-1. 단항, 이항, 삼항 연산자
우선 단항, 이항, 삼항 연산자라는 개념이 등장한다.
이는 필요한 피연산자의 개수에 따라 결정되며, 설명은 다음과 같다.
++x; // 단항 연산자
x+y; // 이항 연산자
(x>y) ? 1 : 0; // 삼항 연산자
- 단항 연산자 : 피연산자 수가 한 개 ex) 증감 연산자, 부호
- 이항 연산자 : 피연산자 수가 두 개 ex) 산술 연산자, 문자열 연산자, 대입 연산자 등
- 삼항 연산자 : 피연산자 수가 세 개 ex) 조건 연산자
1-2. 연산의 방향과 우선순위
우리가 수학을 공부할 때 여러 가지 식을 보았을 것이다.
식은 여러 산술 기호로 구성되어있으며, 각각 계산의 우선순위를 가진다.
예를 들어 괄호가 없는 경우 곱셈, 나눗셈이 1순위, 덧셈, 뺄셈이 2순위인 것 처럼 말이다.
컴퓨터의 연산자 또한 우선순위를 갖는다.
기본적으로 연산 방향은 왼쪽에서 오른쪽으로 진행된다. 증감, 부호, 비트, 논리 등 반대인 경우도 있다.
다음은 연산자들의 연산 방향과 우선순위를 나타낸 것이다.
- 증감 (++ , --) , 부호 (+ , -) , 비트 (~) , 논리 (!) : 연산 방향 : 우 -> 좌
- 산술 (* , / , %)
- 산술 (+ , -)
- 비교 (< , > , <= , >= , instanceof)
- 비교 (== , !=)
- 논리 (& -> ^ -> | 순)
- 대입 (=, +=, -= 등) : 연산 방향 : 우 -> 좌
증감 연산자와 대입 연산자를 제외한 연산자는 모두 연산 방향이 좌 -> 우로 진행된다.
2️⃣ 단항 연산자
2-1. 부호 연산자 (+ , -)
부호 연산자는 양수 및 음수를 표시하는 +,- 를 말한다. 따라서 boolean 과 char 타입을 제외한 기본 타입에서 사용한다.
변수 설정시 default 값은 양수(+) 이다.
여기서 주의해야 할 점은 부호 연산자의 산출 타입이 int 타입이 된다는 것이다.
따라서 계산 결과가 정수형이므로 해당 자료형에 맞게 변수를 설정해야 한다.
예제를 보자.
short s = 100;
short result = -s; // 컴파일 에러
int result = -s; // 정상 실행
1 라인에서 short 타입으로 변수를 저장하였다.
2 라인에서 부호 연산자 '-' 를 이용해 -100을 저장하는데 result 역시 short 타입이다.
그런데 앞서 말했듯이 부호 연산자는 int 타입을 반환하기 때문에, -100 이라는 int 타입이 반환되지만 short 타입 변수에
저장되기 때문에 컴파일 에러가 발생한 것이다.
3 라인에서 int 타입으로 저장하면 정상적으로 실행이 된다.
따라서 각 변수들의 자료형을 잘 설정하는 것이 얼마나 중요한 것인지 다시 한 번 알게 되었다.
2-2. 증감 연산자 (++ , --)
증감 연산자는 처음 C 언어를 공부할 때 많이 헷갈리는 개념이었다.
어쨌든 기존 값에 1을 더하거나 빼는 것인데, 무엇이 다를까? 다음 코드를 보자.
int x=10;
System.out.println(x);
int y=x++;
System.out.println(y);
int z=++x;
System.out.println(z);
- 우선 x 라는 변수에 10을 저장하였다. 따라서 x = 10 이다.
- y = x++ 가 실행될 때, y 에 기존 x 값인 10이 저장된다. 이후 x 값이 1 증가하여 x = 11 이 된다.
- z = ++x 가 실행될 때, 먼저 x 값이 1 증가하여 x = 12 가 된다. 이후 z 에 x 값인 12가 저장된다.
따라서 위 코드의 실행 결과는 차례대로 10, 12, 12 가 나와야 한다.
즉, 전위 연산인 (++x , --x) 는 다른 연산을 수행하기 전에 피연산자의 값을 1 증가, 감소 시킨다.
후위 연산인 (x++, x--) 는 다른 연산을 먼저 수행한 뒤 피연산자의 값을 1 증가, 감소 시킨다.
한 예로 일반적인 for문을 사용할 때 조건식에 들어가는 증감 연산자는 ++i, i++ 모두 상관 없다.
그러나 다른 연산자와 함께 사용하는 연산식에서는 전위, 후위에 따라 결과가 달라질 수 있으니 조심해야 한다.
2-3. 논리 부정 연산자 (!)
논리 부정 연산자는 true <-> false 서로 변경하는 연산자로, boolean 타입에서만 사용할 수 있다.
이는 두 가지 상태 (true / false) 를 번갈아가며 변경하는 toggle 기능을 구현할 때도 사용된다.
boolean result = true; // result : true
result = !result; // result : false
2-4. 비트 반전 연산자 (~)
비트 반전 연산자는 정수 타입의 피연산자에만 사용된다. 이는 피연산자를 2진수로 표현할 때, 비트값인 0 <-> 1 을 서로 변경한다.
연산 후 최상위 비트를 포함하여 모든 비트가 반전되어, 부호가 반대인 새로운 값이 산출된다.
역시 비트 반전 연산자를 사용할 때 주의해야할 점은 부호 연산자와 마찬가지로 산출 값이 int 타입이라는 것이다.
피연산자는 연산 수행 전 int 타입으로 변환되고, 비트 반전이 일어난다.
byte x = 10;
byte y = ~x; // 컴파일 에러
int y = ~x; // 정상 실행
1 라인에서 byte 타입으로 x 에 10을 저장하였다.
2 라인에서 x 값에 비트 연산을 수행한 값을 저장하려 했지만, y는 byte 타입이기 때문에 int 타입인 ~x 값을 저장할 수 없다.
따라서 컴파일 에러가 난다.
3 라인에서 int 타입인 y 에 ~x 를 저장하면 정상적으로 프로그램이 실행된다.
3️⃣ 느낀 점
사실 지금까지 Python, C, C++, Java 등을 공부하면서 변수, 연산자 파트는 대충 넘어갔던 것 같다.
실제로 어떤 연산자들이 있고, 어떻게 사용하는지만 알면 코딩하는데 크게 문제가 되지 않았기 때문이다.
처음부터 공부하던 중 모르는 내용이 없겠다고 자만한 내가 바보였다.
오늘 공부했던 연산자의 반환 타입 등 몰랐던 내용들이 마구잡이로 나왔다. Double.isNaN() 이나 Double.isInfinite() 등의
메소드도 처음 알았다. 따라서 나는 자바를 좀 더 깊게 파볼 생각이다.
단순 코딩만 하는 것이 아니라, 동작 원리나 각 부분별로 깊이 있는 이해를 하고 넘어가야겠다는 생각이 들었다.
다음 글은 나머지인 이항, 삼항 연산자에 관한 내용이 될 것 같다.