본문 바로가기

컴퓨터/Java

연산자

연산자(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