1. 연산자와 피연산자


  • 연산자: 연산을 수행하는 기호
  • 피연산자: 연산자의 연산 수행 대상
  • “모든 연산자는 연산결과를 반환한다.”

2. 연산자의 종류


종류연산자설명
산술 연산자+ - * / % << >>사칙 연산과 나머지 연산(%)
비교 연산자> < ≥ ≤ == ≠크고 작음과 같고 다름을 비교
논리 연산자&&! &^ ~AND 와 OR 으로 조건을 연결
대입 연산자=우변의 값을 좌변에 저장
기타(type) ?: instanceof형변환 연산자, 삼항 연산자, instanceof 연산자

3. 연산자의 우선순위


  • “하나의 식(expression)에 연산자가 둘 이상 있을 때, 어떤 연산을 먼저 수행할 지를 자동 결정하는 것”

4. 연산자의 결합규칙


  • “대입과 단항 연산자를 제외하면, 모두 왼쪽 → 오른쪽”

연산자의 우선순위와 결합법칙은 “세 가지만 기억하자”

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

5. 증감 연산자


  • 증가 연산자(++) 피연산자의 값을 1 증가시킨다.
  • 감소 연산자(--) 피연산자의 값을 1 감소시킨다.
타입설명사용 예
전위형값이 참조되기 전에 증가시킨다.j = ++i;
후위형값이 참조된 후에 증가시킨다.j = i++;
// 전위형
j = ++i;
// 아래와 같다
++i;   // 증가 후에
j = i; // 참조하여 대입
// 실행 이후
i = i
j = i + 1
// 후위형
j = i++;
// 아래와 같다
j = i; // 참조하여 대입 후에
i++;   // 증가
// 실행 이후
j = i
i = i + 1

6. 부호 연산자


public class Ex3_4 {
	public static void main(String[] args) {
		int i = -10;
		i = +i;
		System.out.println(i); // -10
		
		i = -10;
		i = -i;
		System.out.println(i); // 10
	}
}
  • ‘-’는 피연산자의 부호를 반대로 변경
  • ‘+’는 아무런 일도 하지 않는다. (실제 사용 X)

7. 형변환 연산자


형변환이란,

  • 변수 또는 상수의 타입을 다른 타입으로 변환하는 것
(타입)피연산자
double d = 85.4;
int score = (int)d;
변환수식결과
int → char(char)65'A'
char → int(int)'A'65
float → int(int)1.6f1
int → float(float)1010.0f

8. 자동 형변환


자동 형변환이란,

  • 컴파일러가 자동으로 형변환 해주는 것
float f = 1234;        // int타입의 값을 float타입의 변수에 저장
float f = (float)1234; // 자동 형변환
int i = 3.14f;      // 에러
// float의 범위가 int보다 크기 때문에 값손실이 발생할 수 있음
int i = (int)3.14f; // 수동 형변환은 가능
  • “기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환된다.”
byte b = 100;        // OK. byte의 범위(-128 ~ 127)의 값의 대입 (리터럴이기 때문에 가능)
byte b = (byte)100;  // OK. byte로 형변환하여 대입
int i = 100;
byte b = i;          // 에러. int변수에 어떤 값이 들어있는지 확신불가
byte b = (byte)i;    // OK. byte로 형변환하여 대입
byte b = 1000;       // 에러. byte의 범위를 벗어난 값의 대입
byte b = (byte)1000; // OK. 그러나 값 손실이 발생해서 b에는 -24가 저장됨

9. 사칙 연산자


// int 와 int 연산은 int 를 반환
10 / 4 = 2
// int 와 float 연산은 float 를 반환
10 / 4.000000 = 2.500000

10. 산술 변환


산술 변환이란,

  • “연산 전에 피연산자의 타입을 일치시키는 것”
  1. 두 피연산자의 타입을 같게 일치시킨다. (보다 큰 타입으로 일치)
long   + int   -> long
float  + int   -> float
double + float -> double
  1. 피연산자의 타입이 int보다 작은 타입이면 int로 변환된다.
byte + short -> int
char + short -> int

Ex3_9

public class Ex3_9 {
	public static void main(String[] args) {
		int a = 1_000_000;
		int b = 2_000_000;
		long c = a * b;        // a * b 는 int 형으로 계산되기 때문에 오버플로우 발생
		System.out.println(c); // -1,454,759,936
		c = (long)a * b;       // 오버플로우를 방지하기 위해 a 나 b 를 형변환 한 뒤 연산
		System.out.println(c); // 2,000,000,000,000
	}
}

11. 반올림 - Math.round()


  • 실수를 소수점 첫 째자리에서 반올림한 정수를 반환
long result = Math.round(4.52); // result에 5가 저장된다.

Ex3_11

public class Ex3_11 {
	public static void main(String[] args) {
		double pi = 3.141592;
		double shortPi = Math.round(pi * 1000) / 1000.0;
		-> Math.round(3.141592 * 1000) / 1000.0
		-> Math.round(3141.592) / 1000.0
		-> 3142 / 1000.0
		-> 3.142
		System.out.println(shortPi); // 3.142
	}
}

12. 나머지 연산자


  • 오른쪽 피연산자로 나누고 남은 나머지를 반환
  • 나누는 피연산자는 0이 아닌 정수만 허용(부호는 무시됨)
10 % 8  -> 2
10 % -8 -> 2

13. == 연산자와 equals()의 차이


== 연산자

  • 항등 연산자(Operator) 이다.
    • 반의어로 != 가 존재한다.
  • 참조 비교(Reference Comparison) 혹은 주소 비교(Address Comparison)
    • 두 객체가 같은 메모리 공간을 가리키는지 확인한다.
  • 모든 기본 유형(Primitive Types)에 적용할 수 있다.
    • byte, short, char, int, float, double boolean
    • 참조 유형(Reference Types)의 경우 주소값을 비교한다.
    • 사실 Primitive 역시 Constant Pool 에 있는 특정 상수를 참조하기 때문에 주소값을 비교한다고 볼 수 있다.
  • 객체에도 적용이 가능하지만 같은 내용을 가진 서로 다른 객체의 경우 false 를 반환한다.
    • 같은 내용을 갖고 있더라도 주소값이 다르기 때문
  • Boolean Type 으로 반환한다.

equals()

  • 객체 비교 메서드(Method) 이다.
  • 내용 비교(Content Comparison)
    • 두 객체의 값이 같은지 확인한다.
    • 문자열의 데이터/내용을 기반으로 비교한다.
  • 기본 유형(Primitive Types)에 적용할 수 없다.
  • Boolean Type 으로 반환한다.

예시

public class Test {
    public static void main(String[] args) {
        Thread t1 = new Thread();
        Thread t2 = new Thread(); // 새로운 객체 생성. 즉, t1과 다른 객체.
        Thread t3 = t1; // 같은 대상을 가리킨다.
        String s1 = new String("WORLD");
        String s2 = new String("WORLD");
        System.out.println(t1 == t3); // true
        System.out.println(t1 == t2); // false(서로 다른 객체이므로 별도의 주소를 갖는다.)
        System.out.println(t1.equals(t2)); // false
        System.out.println(s1.equals(s2)); // true(동일한 내용을 갖는다.)
    }
}

15. 논리 연산자


  • 조건식을 연결할 때 사용하는 연산자
// i는 2의 배수 또는 3의 배수지만 6의 배수는 아니다.
// && 의 우선순위가 || 보다 높기 때문에 괄호를 적절히 활용해야함
( i % 2 == 0 || i % 3 == 0 ) && i % 6 != 0

16. 논리 부정 연산자


  • ture를 false 로, false는 true로 변경
boolean b = true;
!!b -> !!true -> !false -> true

17. 조건 연산자


  • 조건식의 결과에 따라 연산결과를 달리한다.
조건식 ? 식1 : 식2
result = (x > y) ? x : y;
// x 가 y 보다 크다면 result = x
// y 가 x 보다 크다면 result = y

18. 대입 연산자


  • 오른쪽 피연산자를 왼쪽 피연산자에 저장 후 저장된 값을 반환
System.out.println(x = 3);
System.out.println(3);
  • lvalue - 대입 연산자의 왼쪽 피연산자
    • 저장공간
  • rvalue - 대입 연산자의 오른쪽 피연산자
int i = 0;
3 = i + 3;         // 에러. lvalue가 저장공간이 아님
i + 3 = i;         // 에러. lvalue의 연산결과가 리터럴
final int MAX = 3; // 변수 앞에 키워드 final을 붙이면 상수
MAX = 10;          // 에러. 상수에 새로운 값을 저장할 수 없음

19. 복합 대입 연산자


  • 대입 연산자와 다른 연산자를 하나로 축약
i += 3        <-> i = i + 3;
// 주의. 오른쪽 피연산자가 두개 이상인 경우 괄호를 활용해야함
i *= (10 + j) <-> i = i * (10 + j);