연산자(Operator) & 피연산자(Operand)
연산자 : 연산을 수행하는 기호(+,-,* 등)
피연산자 : 연산자의 작업 대상(변수, 상수, 리터럴, 수식)
x + 3
+ 는 연산자
x,3 은 피연산자
연산자의 종류
개수에 의한 분류
피연산자의 개수로 연산자를 분류하는 것.
1개면 '단항 연산자'
2개 '이항 연산자'
3개 '삼항 연산자'
대부분의 연산자는 '이항 연산자'
삼항 연산자는 '? : ' 하나 뿐. ( a == 1 ? 3:0; a가 1이면 3반환, 아니면 0반환)
연산자의 종류와 우선순위
위에서부터 아래 순서로 진행된다.
- 최우선연산자 ( ., [], () )
- 단항연산자 ( ++, --, !, ~, +/- : 부정, bit변환 > 부호 > 증감)
- 산술연산자 ( *,/,%,+,-,shift) < 시프트연산자 ( >>,<<,>>> ) >
- 비교연산자 ( >,<,>=,<=,==,!= )
- 비트연산자 ( &,|,,~ )
- 논리연산자 (&& , || , !)
- 삼항연산자 (조건식) ? :
- 대입연산자 =,*=,/=,%=,+=,-=
단항연산자와 대입 연산자를 제외한 모든 연산의 진행방향은 왼쪽에서 오른쪽이다.
단항연산자중에서 후위연산자는 연산후에 증감한다.(a++ 등) (아래서 설명함.)
산술 변환
이항 연산자는 두 피연산자의 타입이 일치해야 연산이 가능하다.
이러한 타입 일치를 위해 연산전에 자동 형변환되는 것을 '산술 변환' 또는 '일반 산술 변환'이라고 한다.
이 변환은 이항 연산뿐만 아니라 단항 연산에서도 일어난다.
산술 변환이란?
연산 수행 직전에 발생하는 피연산자의 자동 형변환
1. 두 피연산자의 타입을 같게 일치(보다 큰 타입으로 일치)
2. 피연산자의 타입이 int보다 작은 타입이면 int로 변환
단항 연산자
증감 연산자 ++, --
증감 연산자(++) : 피연산자의 값 1 증가
감소 연산자(--) : 피연산자의 값 1 감소
증감 연산자에는 전위형과 후위형이 있다.
타입 | 설명 | 사용예 |
전위형 | 값이 참조되기 전에 증가 | j = ++i; |
후위형 | 값이 참조된 후에 증가 | j = i++; |
둘의 차이점은 j 에다가 i의 값을 저장할때,
전위형의 경우 i를 먼저 증가한 후에 j에 저장하고,
후위형의 경우 i값을 참조해서 j에 저장한 후 i를 증가한다.
class OperatorEx2 {
public static void main(String args[]) {
int i=5, j=0;
j = i++;
System.out.println("j=i++; 실행 후, i=" + i +", j="+ j); // i = 6, j = 5;
i=5; // 결과를 비교하기 위해, i와 j의 값을 다시 5와 0으로 변경
j=0;
j = ++i;
System.out.println("j=++i; 실행 후, i=" + i +", j="+ j); // i = 6, j = 6;
}
}
단항 연산자엔 이외에도 부호연산자(+ , -), 논리부정 연산자(!), 비트전환 연산자(~)가 있다.
산술 연산자
산술 연산자 우선순위
- 곱셈(*), 나눗셈(/), 나머지(%)
- 더하기(+), 빼기(-)
순으로 우선순위.
나눗셈 사용 시 주의점
- 정수형끼리 사용 시 소수점 이하는 버려짐. 구하기위해선 한쪽을 실수형 타입으로 형변환(나머지는 자동 형변환됨)
- 0으로 나누면 ArithmeticException 발생
- 0.0으로 나누면 Infinity 출력
int보다 작은 타입 산술 시 주의점
byte a = 10;
byte b = 20;
byte c = a+b; // 컴파일 에러 발생
byte c = (byte)(a+b); // 이렇게 명시적 형변환 필요
자바는 int형을 기본으로 산술 연산을 하기 때문에,
byte c = a+b; 시,
a 와 b를 int형을 형변환을 한다음에 계산한다.
그 후, int형을 더 작은 byte형에 저장할려고하고하니 컴파일 에러가 발생한다.
그래서 만약 저장하고 싶으면, 명시적 형변환을 해줘야한다.
그리고 이 과정에서 작은 타입의 범위를 넘으면 값 손실이 발생한다.
int 간 곱셈 시 주의점
int간의 곱셈을 통해 범위를 넘었을 경우에도 원하는 값이 안나올 수 있다.
int a = 1_000_000; // 백만
int b = 2_000_000; // 2백만
long c = a * b; // 원하는 결과 2_000_000_000_000;
// 실제 결과 -1454759936
long c = (long)a * b; // 한쪽을 long타입으로 변경해둬서 미리 long형으로 연산될 수 있게 해야함.
문자 산술 연산 시 주의점
class OperatorEx13 {
public static void main(String[] args) {
char c1 = 'a';
// char c2 = c1+1; // 라인 5 : 컴파일 에러발생!!!
char c2 = 'a'+1; // 라인 6 : 컴파일 에러없음
System.out.println(c2);
}
}
위에서 덧셈 연산자와 같은 이항 연산자는 int보다 작은 타입의 연산자를 int로 자동 형변환한다고 배웠다.
그럼 int + int = int 를 더 작은 타입인 char에 저장하는데 왜 컴파일 에러가 안날까?
그 이유는 'a' + 1이 리터럴 간의 연산이기 때문이다.
상수 또는 리터럴 간의 연산은 실행과정동안 변하는 값이 아니기 때문에,
컴파일 시에 컴파일러가 계산해서 그 결과로 대체함으로 코드를 보다 효율적으로 만든다.
컴파일러가 미리 덧셈연산을 수행하기 때문에 실행 시에는 덧셈 연산이 수행되지 않는다.
컴파일 전 코드 | 컴파일 후 코드 |
char c2 = 'a' + 1; int sec = 60 * 60 * 24; |
char c2 = 'b'; int sec= 86400; |
c1+1처럼 변수가 들어가 있는 경우 컴파일러가 미리 계산할 수 없기 때문에 명시적 형변환을 해줘야한다.
c1+1 -> (char)(c1+1);
비교 연산자
두 피연산자를 비교하는데 사용하는 연산자이다.
연산결과는 참이면 true 거짓이면 false 반환한다.
대소비교 연산자 <, >, <=, >=
두 피연산자의 값의 크기를 비교하는 연산자.
기본형 중에선 boolean을 제외하고 사용 가능
참조형에는 사용 불가.
등가비교 연산자 ==, !=
==은 두 피연산자의 값이 같은지 확인
!=은 두 피연산자의 값이 다른지 확인
모든 자료형에 사용 가능.
기본형의 경우 변수에 저장되어있는 값이 같은지 비교
참조형의 경우 객체의 주소값을 저장하기때문에 같은 객체를 가리키고 있는지 비교
기본형과 참조형간의 비교는 불가(서로 형변환이 불가능함)
실수간의 비교에선 오차로 인해, 생각하지 못한 결과를 얻을 수도 있다.
0.1 == 0.1f 결과 false
0.1은 double 타입으로 15자리의 정밀도를 가지고 있음. 0.100000000000001
0.1f는 float 타입으로 7자리의 정밀도를 가지고 있음. 0.10000000149011612
둘의 비교시엔 값 손실이 일어날수도 있지만,
double타입을 float으로 변경후에 비교해야함.
문자열의 비교
두 문자열의 내용이 같은지 비교하기 위해서는 equals()를 사용해야한다.
==을 통한 비교는 같은 객체인지 비교하는 것이기때문에, 다르게 나올수도 있다.
아래와 같이 equals()를 통해 비교해야 내용 비교가 가능하다.
String str = "abc";
System.out.println(str.equals("abc")); // true 출력
논리 연산자
논리 연산자는 둘 이상의 조건을연결하여 하나의 식으로 표현할 수 있게 해준다.
논리 연산자 - && , || , !
|| (OR 결합) : 피연산자 중 어느 한쪽만 true이면 true 반환
&& (AND 결합) : 피연산자 중 모두 true여야 true 반환
! (논리 부정 연산자) : 피연산자가 true면 false, false면 true를 반환
비트 연산자
비트단위 논리 연산을 함.
관련 글 참조
2022.01.14 - [Algorithm/개념] - [알고리즘 개념] 비트마스크(Bitmask)
참조
'Java의 정석' 책
'Language > Java' 카테고리의 다른 글
[Java] 객체지향언어특징과 클래스와 객체 (0) | 2022.03.01 |
---|---|
[Java] 배열(Array) (0) | 2022.03.01 |
[Java] 형변환(casting) (0) | 2022.02.28 |
[Java] 기본형(Primitive Type) (0) | 2022.02.27 |
[Java] 실수형의 정밀도, 고정소수점과 부동소수점 (0) | 2022.02.27 |
댓글