[JAVA] 연산자

용용학생·2024년 4월 2일

자바

목록 보기
5/32

연산자 : 연산을 수행하는 기호(+, -, *, / 등등)
피연산자 : 연산자의 작업 대상(변수, 상수, 리터럴, 수식)

연산자의 종류

종류결합규칙연산자우선순위
단항 연산자<ㅡㅡ++   --   +   -   ~   !   (type)높음
산술 연산자ㅡㅡ>*   /   %  
ㅡㅡ>+   -
ㅡㅡ><<   >>
비교 연산자ㅡㅡ><   >   <=   >=   instanceof
ㅡㅡ>==   !=
논리 연산자ㅡㅡ>&
ㅡㅡ>^
ㅡㅡ>|
ㅡㅡ>&&
ㅡㅡ>||
삼항 연산자ㅡㅡ>?:
대입 연산자<ㅡㅡ=   +=   -=   *=   /=   %=   <<==   >>==   &=   ^=   |=낮음
  • 단항연산자에 있는 +-는 부호연산자이고, (type)은 형변환 연산자이다
  • instanceof는 객체의 타입을 확인하는 연산자이다.

  • 산술 > 비교 > 논리 > 대입 순으로 실행. 대입은 제일 마지막에 수행된다.
  • 단항 > 이항 > 삼항 순으로 실행. 단항 연산자의 우선순위가 이항 연산자보다 높다.
  • 단항 연산자와 대입 연산자를 제외한 모든 연산의 진행방향은 왼쪽에서 오른쪽이다.

단항 연산자

증감 연산자 ++ --

  • 증가 연산자 (++) : 피연산자의 값을 1 증가시킨다.
  • 감소 연산자 (--) : 피연산자의 값을 1 감소시킨다.
  • 대부분의 피연산자는 피연산자의 타입이나 값을 변경하지 않지만 증감연산자는 변경한다.

증감 연산자가 피연산자의 어느 쪽에 붙느냐에 따라 결과가 다르다.

  • 전위형 : 값이 참조되기 전에 변화시킨다. ex) j = ++i;
    • 피연산자의 값을 먼저 증가시킨 후 변수의 값을 읽어온다.
  • 후위형 : 값이 참조된 후에 변화시킨다. ex) j = i++;
    • 피연산자의 값을 먼저 읽어온 후 값을 증가시킨다.
public class Main {
    public static void main(String[] args) {
		int i=5; j=0;
    
    	j = i++;
    	System.out.println("i=" + i + ", j=" + j);
    
    	i=5;  // 결과 비교 위해 처음 값으로 변경
    	j=0;
    
    	j = ++i;
    	System.out.println("i=" + i + ", j=" + j);
    }
}

결과는 위의 식은 i=6, j=5 가 나오고 아래 식은 i=6, j=6 이 나온다.

주의

증감 연산자를 사용하면 코드가 간결해지지만, 과해진다면 오히려 이해하기 어려워진다.

	int x=5;
    x = x++ - ++x;

이렇게 하나의 식에 여러 번을 작성하는 것을 바람직하지 않다.

  • 하나의 식에서는 증감연산자의 사용을 최소화해야 한다.
  • 식에 두 번 이상 포함된 변수에는 증감연산자를 사용하는 것을 피해야 한다.

산술 연산자

산술 연산자에는 사칙 연산자(+, -, *, /)나머지 연산자(%)가 있다.

산술 연산자는 일상생활에서 자주 사용하는 익숙한 것이라 주의할 것들 몇개만 짚고 가려한다.

우선순위

  • 곱셈(*), 나눗셈(/), 나머지(%) 연산자가 덧셈(+), 뺄셈(-) 연산자보다 우선순위가 높다.

0으로 나눌 때

  • 피연산자가 정수형인 경우, 제수로 0을 사용할 수 없다.
  • 컴파일은 정상적으로 되지만 실행 시 오류가 발생한다.
	System.out.println(3/0); // 실행하면 오류(ArithmeticException) 발생
  • 부동 소수점 값인 0.0f0.0d 로 나누는 것은 가능하다.
	System.out.println(3/0.0f); // Infinity 가 출력됨.

타입에 따른 나눗셈 연산자

  • 나누기 연산자의 두 피연산자가 모두 int 타입인 경우, 연산결과 역시 int 타입이다.
    • 10 / 4 의 연산을 하게 되면 소수점은 버려지고 int 타입의 값인 2를 얻는다.
    • 소수점 자리는 반올림 연산이 아니라 그냥 버려진다.
  • 실수형으로 연산을 해야 소수점까지 얻을 수 있다.
    • 10 / 4.0f 의 연산을 하게 되면 자동 형변환되어 2.5f의 결과를 얻는다.

타입의 형변환이 필요한 연산

	byte a = 10;
    byte b = 20;
    byte c = a + b; // 값 손실 오류 발생
    System.out.println(c);
  • 피연산자를 4바이트 단위로 저장하기 때문에, 정수 연산일 경우 int 타입으로 자동 변환한다.
  • 변수 abint형보다 작은 byte형이기 자료형이 int형으로 변환된다.
  • a+b의 결과가 byte가 아닌 int이기 때문에 타입 에러가 나는 것이다.
  • 연산 수행을 위해서는 명시적 형변환이 필요하다.
	byte a = 10;
    byte b = 20;
    byte c = (byte)(a * b);
    System.out.println(c);

위의 코드의 결과는 44 가 나온다. 결과값으로 300 이 나와야 하지만 형변환에서 배운 것처럼 int형에서 byte형으로 형변환을 했기 때문에 값 손실이 발생하기 때문이다.


	int a= 1_000_000;
    int b = 2_000_000;
    
    long c = a * b;        // a * b = 2,000,000,000,000 ??
    System.out.println(c);
  • 변수 c의 자료형인 long 타입은 2 * 1012를 저장하기 충분하기에 그대로 출력되는 것을 예상한다.
  • 그러나 결과는 전혀 다른 -1454759936 이 출력이 된다.
  • 이유는 int타입과 int타입의 연산 결과는 int타입이기 때문에
    a * b 의 결과가 이미 int 타입의 값이므로 long형으로 자동 형변환되어도 값은 변하지 않는다.
	int a= 1_000_000;
    int b = 2_000_000;
    
    long c = (long)a * b;        
    System.out.println(c);

의도하는 결과를 얻기 위해서는 연산 식에서 형변환을 시켜주어야 한다.


	char c1 = 'a';
    
    char c2 = c1 + 1;   // 라인 2  컴파일 에러; 
    char c2 = 'a' + 1;  // 라인 3 
    c1++;               // 라인 4
  • 라인 2 를 실행하게되면 컴파일 에러가 발생한다.
    • c1 과 1을 연산할 때 int형으로 자동 변환되어 값 손실 오류가 발생
  • 라인 3 은 정상적으로 컴파일된다.
    • 리터럴 간의 연산이어서 컴파일러가 값을 미리 계산해서 그 결과로 대체해놓는다.
  • 라인 4 도 정상적으로 컴파일된다.
    • c1 = c1 + 1; 과 같아보이지만 증감연산자는 컴파일 시 캐스팅되지 않고 그대로 연산되기 때문에 오류가 발생하지 않는다.

조건 연산자

조건 연산자는 조건식, 식1, 식2, 세 개의 피연산자를 필요로 하는 삼항 연산자이다.

  • 조건식 ? 식1 : 식2 의 형태로 사용한다.
  • 조건식true 이면 식1이, false이면 식2가 수행된다.
	if(x > y) {
        result = x;
    } else {
        result = y;
    }

xy의 값을 비교해 큰 값을 result에 넣는 식이다.
이 식을 조건 연산자로 바꾸면 훨씬 간략하게 쓸 수 있다.

    result = (x > y) ? x : y;
  • (x > y)의 조건식을 연산하여 true라면( x 가 크다면) xresult로 저장
  • false라면 yresult로 저장
profile
자바 스프링 공부하는 정리 블로그!

0개의 댓글