연산자는 연산을 수행하는 기호를 말한다.
- 연산자(operator) : 연산을 수행하는 기호
- 피연산자(operand) : 연산의 작업 대상
// 대입연산자(=)도 우변의 값을 좌편에 저장하고 저장된 값을 반환한다. int A = 0; int B = 0 A = b = 1;
종류 | 결합규칙 | 연산자 | 우선순위 |
---|---|---|---|
단항 연산자 | <--- | ++ -- + - ~ ! (type) | 높음 |
산술 연산자 | ---> | * / % | |
+ - | |||
<< >> | |||
비교 연산자 | ---> | < > <= >= instanceof | |
논리 연산자 | ---> | & | |
^ | |||
| | |||
&& | |||
|| | |||
삼항 연산자 | ---> | ? : | |
대입 연산자 | <--- | = += -= *= /= %= <<= >>= &= ^= |= | 높음 |
연산자의 기능이 비슷한 것들끼리 묶어놓은 연산자는 산술, 비교, 논리, 대입 4가지가 있고
피연산자의 개수에 의한 분류한 것으로는 단항 연산자와 삼항 연산자가 있는데 이는 대부분의 연산자는 이항 연산자 이기 때문이다.
단항 연산자의 -(부호 연산자)와 산술 연산자의 -(뺄셈 연산자)는 기호가 같은 경우가 있을 때는 피연산자의 개수로 구분한다.
위와 같이 대부분의 실제 프로그래밍에서 사용되는 식은 수학에서의 우선순위와 같아 판단이 가능하다.
우선순위가 같을 경우에 연산자의 결합규칙을 따른다.
종류 | 결합규칙 | 연산자 | 우선순위 |
---|---|---|---|
단항 연산자 | <--- | ++ -- + - ~ ! (type) | 높음 |
증감연산자는 피연산자에 저장된 값을 1 증가/감소 시킨다.
타입 | 설명 | 예시 |
---|---|---|
전위형(prefix) | 피연산자의 왼쪽에 위치, 값이 참조되기 전에 증가시킨다. | ++i |
후위형(postfix) | 피연산자의 오른쪽에 위치, 값이 참조된 후에 증가시킨다. | i++ |
int i = 5, j = 0; j = i++; //실행시 j = 5, i = 6 i = 5; j = i++; // 실행시 j = 6, i = 6
부호 연산자 '-'는 피연산자의 부호를 반대로 변경한 결과를 반환한다.
int i = -1; // i = -1
i = +i; i = -1
종류 | 결합규칙 | 연산자 | 우선순위 |
---|---|---|---|
산술 연산자 | ---> | * / % | 높음 |
+ - | |||
<< >> | 낮음 |
- 피연산자가 정수일 경우, 나누는 수로 0을 사용할 수 없다(에러 발생)
int a = 0; a = 10 / 0; //에러 발생
- 산술변환이 발생한다.
byte a = 10; byte b = 5; byte c = a + b; // 에러 발생
byte c = (byte)(a + b);
int a = 1_000_000; int b = 1_000_000; long c = a * b;
결과를 저장하는 변수의 자료형이 long이지만, 연산 수행시 연산의 결과가 int 타입 이기 때문에 int의 최대값을 넘어 오버플로우가 발생한다.
c = (long)a * b //또는 a * (long)b로 작성하여 형변환을 해줘야 한다.
마찬가지로 연산의 결과가 int형으로 오버플로우가 발생하는 경우
long a = 1_000_000 * 1_000_000
아래와 같이 작성하여 long 타입 리터럴임을 명시하여 long타입으로 산술 변환이 발생하게 작성해야한다.
long a = 1_000_000 * 1_000_000L // 또는 1_000_000L * 1_000_000L
문자는 해당 문자의 유니코드(정수)로 저장된다. 따라서 정수간의 연산과 동일하다.
문자형으로 이루어진 정수('1')를 정수형으로 변환하는데 사용한다.
- '0' ~ '9'는 유니코드상 연속적으로 배치 되어있다. ('0' = 48, '1' = 49)
- 연속적으로 배치되어 있기 때문에 '0'을 빼는 연산을 통해 실제 정수값을 구할 수 있다.
'1' - '0' = 1
'A' ~ 'Z'와 'a' ~ 'z'도 연속적으로 배치되어 있기 때문에 정수를 더해 원하는 문자를 찾을 수 있다.
char c = 'a'; char c1 = 'c1; char c2 = ' '; c2 = (char)(c1 +1); c1 ++;
- int형으로 변환한 후 덧셈 연산을 수행, 결과가 int형이기 때문에 char형 변수에 저장하기 위해서 형변환이 필요하다.
- 증감연산자(++)는 피연산자 c1에 저장된 값을 1 증가시킨다.
char c = 'a'; char c1 = 'c + 1; // 에러 발생 char c2 = 'a' + 1; // 에러 발생 X
c1 = c + 1의 경우 수식에 변사가 들어가 있어 컴파일러가 미리 계산을 할 수 없어 형변환이 필요해 에러가 발생한다.
c2의 경우 에러가 발생하지 않는데 'a' + 1은 리터럴 간의 연산이기 때문이다.
char c2 = 'a' + 1 // 컴파일 전 char c2 = 'b' // 컴파일 후
상수 또는 리터럴 간의 연산은 실행 과정 동안 변하는 값이 아니기 때문에 컴파일러가 컴파일 시 컴파일러가 계산하여 최적화된 코드를 미리 계산하여 그 결과로 대체하기 때문이다.
int형 간의 나눗셈의 성질을 이용하여 실수의 소수점 버리기
- pi : 3.141592f
- float형 pi * 1000은 float형 3141.592f가 된다.
- int형으로 형변환되어 소수점을 버린다. 3141이 된다.
- int와 float의 연산으로 float형 3.141f가 된다.
- pi : 3.141592
- Math.round 메서드는 매개변수로 받은 값을 소수점 첫째 자리에서 반올림하고 결과를 정수로 반환한다.
- pi * 1000은 double형 3141.592가 된다.
- round 메서드가 첫째 자리에서 반올림한 정수 3142를 반환한다.
- int와 double의 연산으로 double형 3.141가 된다.
왼쪽 피연산자를 오른쪽 피연산자로 나누고 난 나머지 값을 결과로 반환하는 연산자이다.
int a = 10, b = 8; int c = a % n; // 나머지 값 2를 반환한다.
-10 % 8; // -2 10 % -8 // 2 -10 % -8 // -2
두 피연산자를 비교하는데 사용되는 연산자이다. 결과는 오직 true와 false중 하나만을 반환한다.
두 피연산자의 값의 크기를 비교하는 연산자이다.
종류 | 연산자 | 연산결과 |
---|---|---|
비교 연산자 | > | 좌변의 값이 크면 true, 아니라면 false |
< | 좌변의 값이 작으면 true, 아니라면 false | |
>= | 좌변의 값이 크거나 같다면 true, 아니라면 false | |
<= | 좌변의 값이 작거나 같다면 ture, 아니라면 false |
두 피연산자의 값이 같은지 다른지 비교하는 연산자이다.
종류 | 연산자 | 연산결과 |
---|---|---|
비교 연산자 | == | 두 값이 같다면 true, 아니라면 false |
!= | 두 값이 다르다면 true, 아니라면 false |
10.0
double 타입의 값을 float 타입으로 형변화 한 다음 비교해야한다.
실수형은 근사값으로 저장되기 때문에 정확도를 넘어가는 값을 오차가 발생할 수 있다.
double d = 0.1; float f = 0.1f;
d == f :변수 f를 double 타입으로 형변환하여 비교한다. 형변환을 해도 근사값으로 처리한 부분의 값은 변하지 않기 때문에 비교 연산시 false를 반환한다.
(float)d = f : 변수 d를 float 타입으로 형변환하여 비교한다.
비교 연산자가 아닌 equals() 메서드를 사용하여 비교한다.
String str = new String("abc") // 일반적인 객체를 생성 String str = "abc" // 간단히 표현 boolean b = str.equals("abc") // 내용이 같으므로 true가 반환된다.
String str = "abc"; String str1 = new String("abc");
str == "abc" // true str1 == "abcc" // false // 둘의 차이는 나중에 자세히 다룬다. str.equals("abc") // true str1.equals("abc") // true
논리 연산자는 '1보다 크고 10보다 작다'와 같이 둘 이상의 조건을 그리고(AND)와 또는(OR)으로 연결하여 하나의 식으로 표현할 수 있게 해준다.
종류 | 연산자 | 연산결과 |
---|---|---|
논리 연산자 | ||(OR) | 어느 한쪽만 true여도 true를 반환 |
&&(AND) | 양쪽 모두 true여야만 true를 반환 | |
!(NOT) | 피연산자가 true면 false로, false면 true를 반환 |
x는 1보다 크고 10보다 작다
1 < x && x <10
x는 2의 배수 또는 3의 배수지만 6의 배수는 아니다.
(x % 2 == 0 || x % 3 == 0) && x % 6 != 0
문자 x는 대문자 또는 소문자이다.
('a' <= x && x <='z') || ('A' <= x && x <='z')
문자 x는 대문자 또는 소문자가 아니다.
!(('a' <= x && x <='z') || ('A' <= x && x <='z'))
x(피연산자) | y(피연산자) | ||(연산자) |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
x(피연산자) | y(피연산자) | && (연산자) |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
비트 연산자는 피연산자를 비트단위로 논리 연산하는 연산자를 말한다.
종류 | 연산자 | 연산결과 |
---|---|---|
비트 연산자 | (OR) | 피연산자 중 한 쪽의 값이 1이면 1을 결과를 얻는다. 그 외에는 0을 얻는다. |
&(AND) | 피연산자 양 쪽이 모두 1이면 1을 결과를 얻는다. 그 외에는 0을 얻는다. | |
^(XOR) | 피연산자의 값이 서로 다를 때만 1을 결과를 얻는다. 같을 때는 0을 얻는다. |
x(피연산자) | y(피연산자) | x|y(연산자) | x&y (연산자) | x^y(연산자) |
---|---|---|---|---|
1 | 1 | 1 | 1 | 1 |
1 | 0 | 1 | 0 | 1 |
0 | 1 | 1 | 0 | 1 |
0 | 0 | 0 | 0 | 0 |
'|'(OR)는 주로 특정 비트의 값을 변경할 때 사용한다.
- 피연산자중 한쪽의 비트만 1이여도 값이 1로 변경되기 때문에, 변경할 값을 제외한 나머지 비트를 0으로 연산한다면 값을 유지한 채로 변경할 비트의 값을 변경할 수 있다.
'&'(AND)는 주로 특정 비트의 값을 뽑아낼 때 사용한다.
- 피연산자중 한쪽의 비트만 0이여도 값이 0으로 변경되기 때문에 뽑아낼 값을 제외한 비트의 값을 0으로 연산하여 제거한뒤, 뽑아낼 비트의 값은 1로 연산하여 기존 값을 유지 시켜 남은 값을 뽑아낼 수 있다.
'^'(XOR)은 주로 간단한 암호화에 사용된다.
- 피연산자의 비트가 다를 때만 1이되기 때문에, 같은 값을 두고 XOR 연산을 수행하면 원래의 값으로 돌아오는 특징이 있다.
비트 전환 연산자는 피연산자를 2진수로 표현했을 때, 0은 1로, 1은 0으로 바꾸는 연산자이다.
쉬프트 연산자는 2진수로 표현한 피연산자를 이동(shift)시키는 연사자이다.
쉬프트 연산자 (<<)는 부호를 신경쓰지 않고 왼쪽으로 이동 시키며 빈칸을 0으로 채운다.
쉬프트 연산자 (>>)는 부호를 유지시킨다.
피연산자가 음수인 경우, 오른쪽으로 이동시키고 빈자리를 1로 채운다.
피연산자가 양수인 경우, 오른쪽으로 이동시키고 빈자리를 0으로 채운다.
쉬프트 연산자의 연산 결과
조건 연산자는 첫번째 피연산자 (조건문)을 평가하여 평가 결과에 따라 다른 결과를 반환한다.
저장공간(변수)에 값이나 수식의 연산 결과를 저장하는 연산자이다.