연산자란? 연산을 수행하는 기호를 말한다. 예를 들어 '+' 기호는 덧셈 연산을 수행하며, 덧셈 연산자 라고 한다. 자바에서는 사칙연산(+, -, *, /)을 비롯해서 다양한 연산자를 제공한다.
연산자와 피연산자를 조합하여 계산하고자 하는 바를 표현한 것을 '식'이라고 한다. 그리고 식을 계산하여 결과를 얻는 것을 '식을 평가한다'고 한다.
10 * 1 + 3 -> 13
(식) (평가)
연산자의 종류는 아래의 표와 같다.
증감 연산자는 피연산자에 저장된 값을 1 증가 또는 감소시킨다.
증가 연산자(++) 피연산자의 값을 1 증가시킨다.
감소 연산자(--) 피연산자의 값을 1 감소시킨다.
int i = 0;
i++
System.out.println(i) // 1이 출력된다.
i--
System.out.println(i) // 0이 출력된다.
증감연산자에는 전위형과 후위형이 있는데, 둘의 차이는 아래 표와 같다.
int i = 0;
System.out.println(i++); //0이 출력 된 후에 1이증가한다.
System.out.println(i); //1이 출력될 것이다.
------------------------------------------------------
int i = 0;
System.out.println(++i); //1이 증가 된 후에 i가 출력되어 1이 출력될것이다.
부호 연산자'-'는 피연산자의 부호를 반대로 변경할 결과를 반환한다.
부호 연산자'+'는 하는 일이 없으며 쓰이는 경우도 없다.
부호 연산자는 boolean형과 char형을 제외한 기본형에만 사용할 수 있다.
int i = -10;
i = -i;
System.out.println(i); // 10이 출력된다.
형변환이란? 변수 또는 상수의 타입을 다른 타입으로 변환하는 것.
같은 타입뿐만 아니라 서로 다른 타입 간의 연산을 수행해야 하는 경우가 많은데, 이럴 때는 연산을 수행하기 전에 타입을 일치시켜야 한다. 변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환(casting)이라고 한다.
형변환 방법은 아주 간단하다. 형변환 하고자 하는 변수나 리터럴의 앞에 변환하고자 하는 타입을 괄호와 함께 붙옂기만 하면 된다.
(타입)피연산자
여기에 사용되는 괄호()는 캐스트/형변환 연산자라고 한다.
double d = 85.4;
int score = (int)d;
위 식의 과정 ↓
int score = (int)d; -> int score = (int)85.4; -> int score = 85;
형변환의 예시
서로 다른 타입 간의 대입이나 연산시에 먼저 타입을 일치시키는 것이 원칙이지만 경우에 따라 편의상 생략 가능한 경우가 있다.
float f = 1234; //float f = (float)1234; 에서 (float)이 생략됨
위 문장의 우변은 int타입의 상수이고 이 값을 저장하려는 변수의 타입이 float이기에 서로 다른 타입이지만 컴파일러가 자동으로 추가 해 주기 때문에 문제가 없다.
그러나 다음과 같이 값의 범위초과는 에러가 발생한다.
byte b = 1000; //에러 (byte의 범위(-128 ~ 127)를 초과
에러 메세지는 'incompatible types: possible lossy conversion from int to byte' 이렇게 (int)를 묵시적으로 생략해서 byte에 1000이라는 정수형 상수를 저장할 수는 없으나 명시적으로 아래와 같이는 저장할 수 있다. 하지만 위의 에러 메세지처럼 값의 손실이 난다(오버플로우처럼).
byte b = (byte)1000; // OK. 그러나 값 손실에 의해 -24가 저장됨.
컴파일러는 기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환이 되기 때문에 표현범위가 좁은 타입에서 더 넓은 타입으로 형변환 하는 경우에는 값 손실이 없으므로 두 타입 중에서 표현 범위가 더 넓은 쪽으로 형변환된다. 아래 그림은 표현 범위를 시각화 해 두었다. 왼쪽에서 오른쪽으로의 변환은 자동으로 해 주나 오른쪽에서 왼쪽으로는 명시적으로 표현해 주어야 한다.
사칙(+ - * /)연산자는 우리가 아는 수학의 기초와 같다. 하지만 피연산자가 정수형인 경우 0으로는 나눌수 없고 나누려고 시도했을때 zeroDivision오류가 뜰것이다.
만약 우리가 int 10 / int 4를 나누면 현실에서는 2.5라는 값이 나오지만 여기서는 정수형에 소숫점을 저장할 수 없기 때문에 그냥 버려진다. 반올림은 되지 않는다.
이때의 해결법은 위 자동 형변환에서 봤듯이 한쪽을 더 넓은 타입으로 맞춰주면 된다(float/double).
10 / 4.0f -> 2.5f
이항 연산자는 두 피연산자의 타입이 일치해야 연산이 가능하므로, 피연산자의 타입이 서로 다르다면 연산 전에 형변환 연산자로 타입을 일치시켜야한다.
이처럼 연산 전에 피연산자의 타입의 일치를 위해 자동 형변환되는 것을'산술 변환' 또는 '일반 산술 변환'이라 하며, 이 변환은 이항 연산에서만 아니라 단항 연산에서도 일어난다. '산술 변환'의 규칙은 다음과 같다.
1. 두 피연산자의 타입을 같게 일치시킨다.(보다 큰 타입으로 일치)
long + int -> long + long -> long
float + int -> float + float -> float
double + float -> double + double -> double
2. 피연산자의 타입이 int보다 작은 타입이면 int로 변환된다.
byte + short -> int + int -> int
char + short -> int + int -> int
byte a = 10;
byte b = 20;
byte c = a + b;
System.out.prinln(c);
이 코드는 컴파일 오류가 발생하는데 그 이유는 a + b가 반환하는 값이 int이기 때문이다. 이 경우 자동 형변환으로 int -> byte는 되지 않기때문에 명시적으로 형 변환이 이뤄져야 한다.
반올림이 필요한 경우 Math클래스의 round() 메서드를 사용하면 된다. 이 메서드는 소수점 첫째 자리에서 반올림한 결과를 정수로 반환한다
long result = Math.round(4.52);
System.out.println(result); // 5출력
두 문자열을 비교할 때는, 비교 연산자 '=='대신 equals()라는 메서드를 사용한다. String은 기본 자료형이 아닌 클래스중 하나이기에 제공하는 메서드이다.
String str = new String("abc")
// equals()는 두 문자열의 내용이 같으면true, 다르면 false를 결과로 반환
boolean result = str.equals("abc"); //내용이 같으므로 result에 true가 저장됨.
논리연산자는 둘 이상의 조건을 '그리고(AND)'나 '또는(OR)' 혹은 '부정(NOT)'으로 연결하여 하나의 식으로 표현할 수 있게 해준다.
논리 연산자'&&'는 우리말로 '그리고'에 해당하며 두 피연산자가 모두 true때에만 true를 결과로 얻습니다.
논리 연산자'||'는 우리말로 '또는'에 해당하며 두 피연산자 중 하나만 true이면 true를 결과로 얻습니다.
논리 부정 연산자 '!'는 true라면 false를 false라면 true를 결과로 얻습니다.
조건 연산자는 조건식, 식1, 식2 모두 세개의 피연산자를 필요로하는 삼항 연산자이며, 삼항 연산자는 조건 연산자가 하나뿐이다.
result = ( x > y ) ? 식1 : 식2;
위 식에서 괄호는 가독성을 위해 적어둔것이고 실제로는 저 부분이 제일먼저 연산되기에 생략 가능하다.
괄호부분의 조건식이 참이면 식1을 반환하고 거짓이라면 식2를 반환한다.
대입 연산자는 변수와 같은 저장공간에 값 또는 수식의 연산결과를 저장하는데 사용된다.
int x = 3;
대입 연산자는 다른 연산자(op)와 결합하여 'op='와 같은 방식으로 사용될 수 있다.
예를 들어 'i = i + 3'은 'i += 3' 으로 표현 가능하다.