※이 신용권 님의 글은 혼자 공부하는 자바를 공부하고 참고하며 적은 글입니다.
연산자
란 연산에 사용되는 표시나 기호를 말한다.
위 사진과 같이 연산자와 함께 연산되는 데이터를 피연산자라고 한다.
연산자의 종류는 아래와 같다.
연산자 종류 | 연산자 | 피연산자 수 | 산출값 | 기능 |
산술 | +, -, *, /, % | 이항 | 숫자 | 사칙연산 및 나머지 계산 |
부호 | +, - | 단항 | 숫자 | 음수와 양수의 부호 |
문자열 | + | 이항 | 문자열 | 두 문자열을 연결 |
대입 | =, +=, -=, /=, %= | 이항 | 다양 | 우변의 값을 좌변의 변수에 대입 |
증감 | ++, -- | 단항 | 숫자 | 1만큼 증가/감소 |
비교 | ==, !=, >, <, >=, <=, instanseof | 이항 | boolean | 값의 비교 |
논리 | !, &, |, &&, || | 이항 | boolean | 논리 부정, 논리곱, 논리합 |
조건 | (조건식) ? A : B | 삼항 | 다양 | 조선식에 따라 A 또는 B중 하나를 선택 |
피연산자와 연산자의 조합에 따라 정말 많은 연산식이 생성될 수 있지만, 모든 연산식의 공통점은 산술 연산자일 경우는 숫자타입, 비교 연산자와 논리 연산자는 논리 타입으로 결괏값이 나온다.
//example code
int x = 4, y = 2;
boolean result = (x + y) < 5; //false
비교 연산자인 <의 왼쪽 피연산자로 (x+y), 오른쪽 피연산자로 5가 사용된 연산식이 있다.
위에서 설명했듯 연산자가 비교 연산자가 사용되었으므로 피연산자가 int(정수) 타입이라고 해도 결괏값은 boolean 타입이 나온다.
연산의 방향과 우선순위
연산식은 다양한 연산자와 피연산자가 복합적으로 구성된 경우가 많다.
예를 들어 단순한 2 * 8이 아닌 2 * (8+12) / 2 + ...와 같은 식이다.
사칙연산 같은 경우는 보통의 수학과 같다. 곱셈(*) 나눗셈(/)이 덧셈(+) 뺄셈(-)보다 우선 연산되고, 괄호()로 우선순위를 높혀줄 수 있다.
그렇다면 비교연산자나 대입연산자 같은 경우는 어떨까?
연산자끼리의 우선순위는 명확하게 정해져있고, 같은 우선순위끼리의 대부분의 연산자는 왼쪽에서 오른쪽 방향으로 연산을 수행한다.
연산자의 우선순위와 연산 방향은 아래와 같다.
연산자 | 연산 방향 | 우선순위 |
증감(++, --), 부호(+, -), 논리(!) | <ㅡ | ^ 높음 낮음 v |
산술(*, /, %) | ㅡ> | |
산술(+, -) | ㅡ> | |
비교(<, >, <=, >=, instanceof) | ㅡ> | |
비교(==,!=) | ㅡ> | |
논리(&) | ㅡ> | |
논리(^) | ㅡ> | |
논리(|) | ㅡ> | |
논리(&&) | ㅡ> | |
논리(||) | ㅡ> | |
조건(?:) | ㅡ> | |
대입(=, +=, -=, *=, /=, %=) | <ㅡ |
//example code
int num = 100 * 2 / 3 % 5; //모두 같은 우선순위를 가진 연산자이기에 왼->오 방향으로 연산이 수행됨.
//1. 200 / 3 / % 5
//2. 66 % 5
//3. 1
int num1 = num2 = num3 = 100 //대입연산자는 오->왼 방향으로 연산이 수행됨.
//1. num3 == 100;
//2. num2 == 100;
//3. num1 == 100;
int result = (100 + 20) * 4; //곱의 우선순위가 덧셈보다 높지만 괄호()가 먼저 수행됨.
//1. 120 * 4
//2. 480
연산자의 종류
연산자의 종류는 필요로 하는 피연산자의 수에 따라 정해지고, 종류로는 단항, 이항, 삼항 연산자가 있다.
단항 연산자: ++x;
이항 연산자: x + y;
삼항 연산자: (x > y) ? "true" : "false"
단항 연산자
피연산자가 단 하나뿐인 연산자를 말한다.
단항 연산자의 종류로는 부호 연산자(+, -), 증감 연산자(++, --), 논리 부정 연산자(!)가 있다.
부호 연산자는 변숫값의 부호를 유지하거나 바꾸기 위해 주로 사용된다.
+는 부호를 유지하고 -는 부호를 바꾸는 데 사용되며 +는 생략 가능하다.
//example code
int num00 = +10; //int num00 = 10과 같다.
int num01 = -10;
int num02 = +(-10); //-10
int num03 = -(-10); //10
ab = +ab
-ab = -(ab) = +(-ab)
-(-ab) = -1 * (-ab) = ab
와 같이 수학적으로 접근해도 이해하기 좋다.
부호 연산자의 결과는 항상 int 타입이다.
byte 타입이나 int보다 범위가 적은 정수 타입으로 연산을 실행하면 자동으로 int 타입으로 변환되어서 byte 타입 변수에 저장하게 되면 컴파일 에러가 난다.
증감 연산자는 변수의 값을 1 증가시키거나 1 감소시키는 연산자를 말한다.
//example code
int a = 1;
int b = a++; //b == 2
int c = ++a + 10; //c == 2
int d = a--; //d == 0
int e = --a; //e == 0
단순하게는 위와 같이 사용할 수 있다.
증가 연산자와 감소 연산자는 변수의 앞뒤 어디에든 올 수 있으며, 연산식에서 증감 연산자만 사용된다면 증감 연산자의 위치는 상관없다.
반면에 증감 연산자가 다른 연산자와 같이 사용된다면 연산식에서 증감 연산자의 위치는 연산식에 영향을 준다.
우선 증감 연산자가 변수 앞에 있으면 우선 변숫값을 1 증가 혹은 1 감소시킨 후에 다른 연산자를 처리한다.
또한, 증감 연산자가 변수 뒤에 있으면 다른 연산자를 먼저 처리한 후 변숫값을 1 증가 또는 1 감소시킨다.
//example code
int a = 1;
int b = 2;
int result01 = ++a + 10; //result01 == 12
int result02 = b++ + 10; //result02 == 3
- result01의 연산 과정
- ++a : a에 2가 대입됨
- a + 10 == 2 + 10 == 12
- result01 == 12
- result02의 연산 과정
- b + 10 == 2 + 10 == 12 //++b는 가장 마지막에 연산되므로 2+10이 먼저 수행
- b++ == 2 + 1 == 3 //b++는 b에 1을 더한값을 b에 대입하으로 3 (->+10의 존재 의미가 사라짐)
- result02 == 3
※i++과 i+=1의 연산 속도의 차이는 없다.
논리 부정 연산자란 true를 false로 false를 true로 변경하는 연산자로 boolean 타입의 연산에만 사용된다.
이항 연산자
피연산자가 2개인 연산자를 말한다.
이항 연산자의 종류로는 산술 연산자, 문자열 결합 연산자, 비교 연산자, 논리 연산자, 대입 연산자 등 가장 많은 종류를 가지고 있다.
간단하게 설명하자면...
산술 연산자는 산술끼리의 연산을 수행을
문자열 결합 연산자는 문자열끼리의 결합을
비교 연산자는 두 피연산자끼리의 비교를
논리 연산자는 두 피연산자끼리의 동일 여부를
대입 연산자는 오른쪽항에 왼쪽항을 대입한다.
산술 연산자의 특징은 피연산자들의 타입이 같지 않으면 피연산자들의 타입을 일치시킨 후 연산을 수행한다는 점이다.
- 피연산자들이 byte, short, char 타입일 경우 모두 int 타입으로 변환된 후에 연산을 수행한다.
- 피연산자들이 모두 정수 타입이고 long 타입이 포함되어 있으면, 모두 long 타입으로 변환된 후 연산을 수행한다.
- 피연산자 중 실수 타입(float, double)이 있을 경우 허용 범위가 큰 실수 타입으로 변환된 후 연산을 수행한다.
산술 연산자에서 주의할 사항은 원하는 값의 타입을 정확히 하고 연산할 때 해당 타입으로 연산을 해줘야 한다는 점이다.
//example code
int intNum1 = 10;
int intNum2 = 4;
int intResult = intNum1 / intNum2; //2
double doubleResult = intNum1 / intNum2; //2.0
수학적으로 봤을 때 10 / 4는 2.5가 나와야 하지만 int 타입은 소수점 이하 부분을 버리고 2만 산출한다.
앞에서 대입 연산자는 오른쪽에서 왼쪽으로 수행된다고 말했었는데
즉 실수로 저장하는 변수 doubleResult도 intNum1 / intNum2에서 2의 값을 먼저 산출한 후 대입을 받아오면서
자동 타입 변환으로 인해 2.0이 된다.
그렇다면 내가 원하는 대로 2.5를 받으려면 어떻게 해야 할까?
무조건 실수 타입으로 값을 받고 싶다면 피연산자 중 하나는 실수 타입이여야 한다.
애초에 변수 초기화를 할 때 double로 하나를 선언하든지 아니면 연산 중 int 타입 중 최소한 하나를 실수 타입으로 강제 변환 시켜야 한다.
//example code
int intNum1 = 10;
int intNum2 = 3;
double result01 = (intNum1 * 1.0) / intNum2;
double result02 = (double) intNum1 / intNum2;
double result03 = intNum1 / (double) intNum2;
※char 타입도 정수 타입이므로 산술 연산이 가능하지만, 주의할 점은 int 타입으로 변환되므로 연산 결과는 int 타입이 된다.
문자열 결합 연산자에서 주의할 점은 피연산자 중 한쪽이 문자열이 아닌 정수나 실수이면 해당 변수도 문자열이 된다.
이때 결합 과정은 연산 우선순위에 영향을 많이 받는다.
String str1 = "Hello" + "World"; //Hello World
String str2 = "JDK" + 3 + 3.0; //JDK33.0
String str3 = 3 + 3.0 + "JDK"; //6.0JDK
String str4 = "JDK" + (3 + 3.0); //JDK6.0
str1 해석:
"Hello"와 "World" 문자열을 결합했다.
str2 해석:
+끼리 우선순위는 같으므로 오른쪽에서 왼쪽으로 연산이 수행됐다.
- "JDK" + 3 + 3.0
- "JDK3" + 3.0
- "JDK33.0"
str3 해석:
+끼리의 우선순위는 같으므로 오른쪽에서 왼쪽으로 연산이 수행됐다.
- 3 + 3.0 + "JDK"
- 6.0 + "JDK"
- "6.0JDK"
str4 해석:
+끼리의 우선순위는 같지만 괄호()가 있으므로 괄호먼저 연산을 수행한다.
- "JDK" + (3 + 3.0)
- "JDK" + 6.0
- "JDK6.0"
비교 연산자의 종류는 아래와 같다.
구분 | 연산식 | 설명 | ||
동등 비교 |
피연산자1 | == | 피연산자2 | 두 피연산자 값이 같은가? |
피연산자1 | != | 피연산자2 | 두 피연산자 값이 다른가? | |
크기 비교 |
피연산자1 | > | 피연산자2 | 피연산자1의 값이 피연산자2의 값보다 초과인가? |
피연산자1 | < | 피연산자2 | 피연산자1의 값이 피연산자2의 값보다 미만인가? | |
피연산자1 | >= | 피연산자2 | 피연산자1의 값이 피연산자2의 값보다 이상인가? | |
피연산자1 | <= | 피연산자2 | 피연산자1의 값이 피연산자2의 값보다 이하인가? |
비교 연산자에서 주의할 점은
첫 번째로 만약 피연산자가 char 타입이라면 유니코드 값으로 비교 연산을 수행한다.
두 번째로 float 타입의 0.1과 double 타입의 0.1은 다른 값이다. float은 0.1의 근사값(0.10000000149011612)이기 때문이다.
float 타입의 값으로 비교 연산자를 사용하고 싶다면 피연산자를 모두 float 값으로 변환해주거나, 정수 타입으로 변환해주고 비교하는 것이다.
논리 연산자의 종류로는 논리곱(&&), 논리합(||), 배타적 논리합(^), 논리 부정(!)이 있다.
논리 연산자는 boolean 타입만 사용할 수 있다.
구분 | 연산식 | 결과 | 설명 | ||
AND (논리곱) |
true | && 또는 & |
true | true | 피연산자 모두가 true일 결우에만 연산 결과가 true |
true | false | false | |||
false | true | false | |||
false | false | false | |||
OR (논리합) |
true | || 또는 | |
true | true | 피연산자 중 하나만 true이면 연산 결과는 true |
true | false | true | |||
false | true | true | |||
false | false | false | |||
XOR (베타적 논리합) |
true | ^ | true | false | 피연산자가 하나는 true이고 다른 하나가 false일 경우에만 연산 결과가 true |
true | false | true | |||
false | true | true | |||
false | false | false | |||
NOT (논리 부정) |
! | true | false | 피연산자의 논리값을 바꿈 | |
false | true |
&&와 & 는 산출 결과는 같지만 &는 두 피연산자 모두를 평가해서 산출 결과를 내고, &&는 앞의 피연산자가 fALse라면 뒤의 피연산자를 평가하지 않고 바로 false를 산출해 결과를 낸다. (||와 |도 같음.)
즉 &나 |을 사용하는 것보다 &&, ||를 사용하는 것이 더 효율적으로 동작한다.
대입 연산자는 오른쪽 피연산자의 값을 왼쪽 피연산자인 변수에 저장한다.
종류로는 단순히 오른쪽 피연산자의 값을 변수에 저장하는 단순 대입 연산자와
정해진 연산을 수행한 후 결과를 변수에 저장하는 복합 대입 연산자가 있다.
구분 | 연산식 | 설명 | ||
단순 대입 연산자 | 변수 | = | 피연산자 | 오른쪽 피연산자의 값을 왼쪽 변수에 저장 |
복합 대입 연산자 | 변수 | += | 피연산자 | 변수=변수 + 피연산자와 동일 |
변수 | -= | 피연산자 | 변수=변수 - 피연산자와 동일 | |
변수 | *= | 피연산자 | 변수=변수 * 피연산자와 동일 | |
변수 | /= | 피연산자 | 변수=변수 / 피연산자와 동일 | |
변수 | %= | 피연산자 | 변수=변수 % 피연산자와 동일 | |
변수 | &= | 피연산자 | 변수=변수 & 피연산자와 동일 | |
변수 | |= | 피연산자 | 변수=변수 | 피연산자와 동일 | |
변수 | ^= | 피연산자 | 변수=변수 ^ 피연산자와 동일 |
대입 연산자는 모든 연산자 중에서 가장 낮은 연산 순위를 가지고 있으므로 가장 마지막에 수행된다.
대입 연산자의 연산 진행 방향은 오른쪽에서 왼쪽이다.
삼항 연산자
삼항 연산자는 3개의 피연산자를 필요로 하는 연산자다.
조건문으로 사용되어서 조건 연산식이라고도 부른다.
int num0 = 10;
int num1 = 20;
System.out.println((num0 > num1) ? "큽니다" : "작습니다";) //큽니다
첫 번째 피연산자에는 조건식이 들어간다.
조건식을 연산하여 true가 나오면 삼항 연산자의 결과는 두 번째 피연산자가 출력,
조건식을 연산하여 false가 나오면 삼항 연산자의 결과는 세 번째 피연산자가 출력된다.
읽어주셔서 감사합니다. (0^0)
'📖혼자공부하는자바' 카테고리의 다른 글
Chapter 04-2 Math.random() (0) | 2022.11.13 |
---|---|
Chapter 04-1 조건문 (0) | 2022.11.13 |
Chapter 02-4 변수와 시스템 입출력 (0) | 2022.11.10 |
Chapter 02-3 타입 변환 (0) | 2022.11.08 |
Chapter 02-2 기본 타입 (0) | 2022.11.08 |