연산자(operator)는 연산을 수행하는 기호를 뜻하는 것으로 사칙연산을 비롯해 다양한 연산자들이 있다.
연산을 수행하려면 반드시 연산의 대상이 있어야하는데 이를 피연산자(operand)라고 한다.
연산자의 종류
종류 | 연산자 | 설명 |
산술 연산자 | +, -, *, /, %, <<, >> | 사칙연산과 나머지 연산 |
비교 연산자 | >, <, >=, <=, ==, != | 크고 작음과 같고 다름을 비교 |
논리 연산자 | &&, ||, !, &, |, ^, ~ | 그리고와 또는으로 조건을 연결 |
대입 연산자 | = | 우변의 값을 좌변에 저장 |
기타 | (type), ?:, instanceof | 형변환 연산자, 삼항 연산자, instanceof 연산자 |
연산자의 우선순위는 산술 > 비교 > 논리 > 대입이고, 단항 > 이항 > 삼항의 순서대로 우선순위가 주어진다.
그리고 산술 연산자 중에서 쉬프트 연산자는 덧셈 연산자보다 우선순위가 낮고, 논리 연산자의 우선순위는 & > ^ > | > && > || 순서대로 되어있다.
산술 변환
연산을 할 때 두 피연산자의 타입이 일치해야 연산이 가능하다.
따라서 서로다른 타입이 있을 때 연산을 위해 피연산자의 타입을 자동으로 형변환하여 연산을 하게 된다.
이때 피연산자의 타입을 큰 쪽으로 일치시키게 되고, 만약 피연산자의 타입이 int보다 작은 타입이면 int로 변환을 한다.
int로 변환해주는 이유는 정수형의 기본 타입이여서 가장 효율적으로 처리가 가능하고, 이보다 더 작게 되면 표현 범위가 좁아서 오버플로우가 발생할 가능성이 높다.
단항 증감 연산자
단항 연산자의 경우 기본적으로 피연산자의 왼쪽에 위치하지만 단항 증가, 단항 감소 연산자의 경우 오른쪽에 위치할 수도 있다.
이 두 경우의 차이점은 후위형으로 연산을 할 경우 변수의 값을 읽어온 다음에 연산이 반영되어 연산의 결과가 반영되지 않고 참조를 하게 된다.
class Operator {
public static void main(String [] args){
int i = 5, j = 0;
j = i++;
System.out.println("j = i++; 실행 후, i = " + i + ", j = " + j);
i = 5;
j = 0;
j = ++i;
System.out.println("j = ++i; 실행 후, i = " + i + ", j = " + j);
}
}
결과:
j = i++; 실행 후, i = 6, j = 5
j = ++i; 실행 후, i = 6, j = 6
class Operator {
public static void main(String [] args){
int i = 5;
System.out.println(i++ - ++i);
}
}
결과:
-2
산술 연산자
위에서 언급했다시피 int보다 작은 type의 연산의 경우 자료형을 int로 변환한 다음 연산을 수행한다.
따라서 아래의 a + b의 연산 결과는 int로 나오기 때문에 int변수를 byte에 형변환 없이 저장을 하려고 하여 에러가 발생하게 된다.
따라서 따로 type을 지정해야 에러가 발생하지 않는다.
class Operator {
public static void main(String [] args){
byte a = 10;
byte b = 20;
byte c = a + b;
System.out.println(c);
}
}
결과:
java: incompatible types: possible lossy conversion from int to byte
수정
class Operator {
public static void main(String [] args){
byte a = 10;
byte b = 20;
byte c = (byte) (a + b);
System.out.println(c);
}
}
결과:
30
만약 아래의 코드와 같이 연산을 하게되면 따로 형변환하는 과정 없이 int로 변환되지 않고 결과가 출력되게 된다.
class Operator {
public static void main(String [] args){
char c = 'a' + 1;
System.out.println(c);
}
}
결과:
b
이러한 연산이 가능한 이유는 지금 위의 코드가 리터럴간의 연산을 수행하기 때문이다.
상수나 리터럴 값은 실행과정에서 변하는 값이 아니기 때문에 컴파일을 하는 과정에서 컴파일러가 해당 값 그대로 사용하여 연산을 수행한다.
하지만 이전의 경우 수식에 변수를 사용하였기 때문에 컴파일러가 미리 해당 변수의 값을 계산할 수 없기 때문에 형변환이라는 과정을 통해서 형변환을 해주는 과정이 필요하다.
비교 연산자
비교연산자의 경우 기본적인 것은 다른 언어와 동일하나 특별히 두 문자열을 비교할 때 비교 연산자 '=='를 사용하는 것이 아니라 equals()라는 메서드를 사용해야 한다.
왜냐하면 아래와 같이 새로운 객체를 생성한 경우 같은 문자를 나타내지만 결과가 다르게 나오는 경우가 있기 때문이다.
class Operator {
public static void main(String [] args){
String str1 = new String("abc");
System.out.printf("str1 == \"abc\" %b%n", str1 == "abc");
System.out.printf("str1.equals(\"abc\") %b%n", str1.equals("abc"));
}
}
결과:
str1 == "abc" false
str1.equals("abc") true
'컴퓨터 > Java' 카테고리의 다른 글
변수 (0) | 2024.11.09 |
---|---|
자바 시작하기 전에 (1) | 2024.11.07 |