연산자 (Operator)
- 연산자 : 프로그램에서 데이터를 처리해 결과를 산출하기 위해 사용되는 표시 / 기호
- 피 연산자 : 계산, 연산자의 대상
산술연산자 (Arithmetric Operator)
- 산술 연산자 - 2개의 피연산자를 필요로 한다.
- boolean과 참조 자료형은 사용할 수 없지만 기본 자료형은 산술 연산자로 연산이 가능하며 String은 예외적으로 + 연산이 가능.
- String 문자열끼리 + 하는 경우 문자열을 더해서 나온 문자열을 만든다.
- 등호 (assignment operator) : 대입 연산자
- 왼쪽의 변수에 오른쪽 값을 대입할 때 사용하는
- 변수에 값을 여러 번 할당 시 기존에 있던 값은 사라지고 새로운 값이 변수에 할당된다.
- + (additive operator) : 더하기 연산자
- - (subtraction operator) : 빼기 연산자
- * (multiply operator) : 곱하기 연산자
- / (division operator) : 나누기 연산자
- 정수형 / 정수형으로 계산시 정수형으로 계산이 된다.
- 어떤 수를 0으로 나누는 경우 나눌 수 없기 때문에 예외가 발생한다.
- ex) 5 / 10 == 계산 결과 0.5가 아닌 0이 나온다. (실수형으로 계산해야 0.5가 나온다)
- % (remainder operator) : 나머지 연산자
- 나머지 값을 구하는 연산자
- ex) 53 % 10 == 3
- boolean과 참조 자료형은 사용할 수 없지만 기본 자료형은 산술 연산자로 연산이 가능하며 String은 예외적으로 + 연산이 가능.
- 수학과 같이 ()로 묶어서 계산하면 다른 것보다 우선 순위가 높아져 먼저 계산을 수행한다.
- 우선 순위가 애매하거나 조금이라도 복잡한 경우 ()를 통해 명확하게 표현하는 것이 좋다.
String str = "a + b = " +10;
//출력 결과 a + b = 10
// 주의할 점
// 1번방식
String str2 = "점수 = " + 80 + 5 ;
//출력 결과 점수 = 805
// 2번방식
String str3 = "점수 = " + (80 + 5) ;
//출력 결과 점수 = 85
- 문자열과 다른 타입을 더하는 경우 다른 타입을 문자열로 변환 후 문자열 + 문자열로 계산하게 된다.
- 문자열과 숫자를 더할 경우 주의할 점!!
- 문자열과 숫자가 만나면 문자열이 되기 때문에 주의해서 사용해야한다.
- 1번 방식과 2번 방식의 차이는 괄호의 여부다.
- 1번 방식은 문자열 + 숫자 + 숫자 형태로 앞에서부터 계산이 된다.
- (문자열 + 숫자) + 숫자 => 문자열 + 숫자 => 문자열
- 그렇기에 점수 = 80이라는 문자열이 되고 + 5를 계산하게 돼서 점수 = 805라는 결과가 나오게 된다.
- 2번 방식은 문자열 + (숫자 + 숫자) 형태로 괄호부터 계산 후 앞에서부터 계산을 한다.
- 문자열 + (숫자 + 숫자) => 문자열 + 숫자 => 문자열
- 그렇기에 80+5 = 85가 결과로 나오고 점수 = 85라는 결과가 나오게 된다.
복합 대입 연산자 (Compound Assignment Operator)
- 복합 대입 연산자
- 산술 연산자에서 대입 연산자(=)와 나머지 산술 연산자(+,-,*,/,%) 기호를 붙여서 사용하는 방식
ex) Compund Assignment Operator Example
int a = 10;
a = a + 10; // 일반적인 산술 연산자를 통한 연산
// 복합 대입 연산자 사용
a += 10; // a에 10을 더한 값을 a에 할당하라는 의미로 위 식과 동일한 의미
a -= 3; // a에 3을 뺀 값을 a에 할당
a *= 2; // a에 2를 곱한 값을 a에 할당
a /= 5; // a에서 5를 나눈 값을 a에 할당
a %= 6; // a에서 6을 나눈 나머지 값을 a에 할당
단항 연산자 (Unary Operator)
- 단항 연산자 - 1개의 피연산자를 필요로 하는 연산자
- + : 단항 플러스 연산자
- *(+1)과 동일한 연산
- - : 단항 마이너스 연산자
- *(-1)과 동일한 연산
- ++ : 증가 연산자
- +1 연산과 동일, 공백 없이 + 두 개를 반드시 붙여줘야한다.
- ++이 변수 앞에 오는 경우와 뒤에 오는 경우가 존재
- 전위 증감 연산자(앞에 오는 경우) : 변수를 참조하기전에 +1 연산
- 후위 증감 연산자(뒤에 오는 경우) : 변수를 참조한 후에 +1 연산
- -- : 감소 연산자, 공백 없이 - 두 개를 반드시 붙여줘야한다.
- -1 연산과 동일
- ++ 증가 연산자와 동일하게 앞에 오는 경우와 뒤에 오는 경우가 존재
- ! : 논리 부정 연산자
- boolean 타입에서만 사용가능한 연산자
- boolean 값 앞에 연산자를 붙여주면 결과가 반대가 된다.
- !true -> false
- !false -> true
- ~ (틸드)
- 2진수로 되어 있는 bit 값을 전부 거꾸로 바꾼다 (반전).
- + : 단항 플러스 연산자
ex) Unary Operator Example
int num = -10;
// 단항 플러스(마이너스) 연산자
int result = +num; // result = num * +1 과 동일한 의미, result == -10
result = -num; // result = num * -1 과 동일한 의미, result == 10
// 증가(감소) 연산자
num++; // num = num + 1; 과 동일
num--; // num = num - 1; 과 동일
// 증가(감소) 연산자 변수 앞 / 뒤 경우
int a = 1;
System.out.println(a++); // println() 메소드로 결과 출력 후 +1 연산
System.out.println(++a); // +1 연산 후 println() 메소드로 결과 출력
// 논리 부정 연산자
boolean flag = true;
System.out.println(!flag); // 논리 부정 연산자에 의해 결과가 반대가 되어 false 출력
// 틸드 연산자
byte b = 1;
System.out.println(~b); // 틸드 연산자에 의해 비트 반전 후 값이 음수이므로 2의 보수법에 의해 -2 출력
// 전위 증감 연산자
int a = 1, b = 0;
b = ++a;
// 수행 결과 a = 2, b = 2
// 후위 증감 연산자
int a = 1, b = 0;
b = a++;
// 수행 결과 a = 2, b = 1
// b = ++a; 전위 연산을 분해하면
a = a + 1;
b = a;
// b = a++; 후위 연산을 분해하면
b = a;
a = a + 1;
- ++, -- 증감 연산자가 앞에 오는지 뒤에 오는지에 따라 계산 순서가 달라진다.
- 전위 연산은 먼저 증감 연산 후 다른 계산 / 대입을 하게 되고 후위 연산은 먼저 다른 계산 / 대입 후 증감 계산을 하게 된다.
- 단독으로 전위, 후위 증감 연산자를 사용하는 경우 둘 다 결과는 같다.
비교 연산자
- 비교 연산자: 두 개의 피연산자를 비교하는 연산자로 연산 결과는 true / false
- 등가 비교 연산자 (Equality Operator)
- == : 같음
- != : 같지 않음
- 등가 비교 연산자는 모든 타입에서 사용가능
- 기본 자료형 / 참조 자료형 모두 사용가능
- 기본 자료형에서는 같은 종류끼리 비교 가능 (숫자는 숫자끼리, boolean은 boolean끼리만)
- 참조 자료형에서는 값이 아닌 서로의 주소 값이 같은지 확인한다.
- String 문자열은 기본 자료형이 아닌 참조 자료형이므로 문자열의 값 비교 시 ==이 아닌 equals() 메소드를 사용해야 한다.
- 대소 비교 연산자 (Relational Operator)
- > (대소 비교 연산자) : 왼쪽 값이 큼
- >= (대소 비교 연산자) : 왼쪽 값이 크거나 같음
- < (대소 비교 연산자) : 오른쪽 값이 큼
- <= (대소 비교 연산자) : 오른쪽 값이 크거나 같음
- boolean / 참조 자료형에서는 사용할 수 없다.
- 부등호와 등호의 순서가 바뀌면 안된다.
- 등가 비교 연산자 (Equality Operator)
ex) Relational Operator Example
int num1 = 1;
int num2 = 2;
int num3 = 1;
// == 연산자
System.out.println(num1 == num2); // 1 != 2 이므로 false 출력
System.out.println(num1 == num3); // 1 == 1 이므로 true 출력
// != 연산자
System.out.println(num2 != num3); // 1 != 2 이므로 true 출력
// >, < 연산자
System.out.println(num1 > num2); // 1 < 2 이므로 false 출력
// <=, >= 연산자
System.out.println(num1 >= num3); // 1 >= 1 이므로 true 출력
논리 연산자 (Conditional Operator)
- 논리 연산자: 여러 조건이 있는 경우 비교할 수 있는 연산자
- && : AND 결합.
- 모두 true 일때만 true
- || : OR 결합.
- 하나라도 true라면 true
- && : AND 결합.
ex) Conditional Operator Example
boolean x = true;
boolean y = false;
System.out.println(x || y); // true || false 이므로 true 출력
System.out.println(x && y); // true && false 이므로 false 출력
삼항 연산자
- ?: 연산자: if 문장을 간단하게 처리할 수 있는 연산자
- 조건이 있는 문장을 한 줄로 처리 가능하다.
- if 문장보다 가독성 측면에서 떨어진다.
- = 왼쪽에 있는 변수에 값을 할당할 때 사용한다.
- 변수 = (boolean 조건식) ? true일때 값 : false일때 값
- () 괄호 안의 값은 반드시 boolean 결과를 제공 (true / false)
- true / false일때 값은 숫자, boolean형, 참조 자료형 모두 가능하다. (좌측 변수 타입에 맞출 것)
- 조건이 있는 문장을 한 줄로 처리 가능하다.
비트 연산자 (Bitwise Operator)
- 비트 연산자: 비트 단위로 데이터를 처리할 때 사용하는 연산자 (실수형에는 사용할 수 없음)
- bitwise 연산자 : 두 개의 숫자를 비교하는 연산자
- & : AND 연산, 두 값이 모두 true(1)일 경우에만 true(1)
- 논리 연산자 &&와 비트 연산자 & 의 차이점
- &&의 경우 좌측에 있는 연산이 false 면 우측 연산을 수행하지 않음 (두 개의 연산 모두 true여야 결과가 true 이기에)
- & 의 경우 좌측 연산 결과와 우측 연산 결과를 비교해야 하기에 모든 연산을 수행
- | : OR 연산, 두 값이 모두 false(0)일 경우에만 false(0) (inclusive OR 연산)
- ^ : XOR 연산, 두 값이 서로 다를 경우에만 true(1), 모두 true(1) / false(0)면 false (0) (exclusive OR 연산)
- & : AND 연산, 두 값이 모두 true(1)일 경우에만 true(1)
- unary 연산자 : 한 개의 숫자만 있어도 되는 연산자
- ~ : unary 연산 (Not 연산)
- 각 bit의 값을 반대로 바꾼다.
- 최상위 비트가 1(음수)이라면 2의 보수를 구한다.
- ~ : unary 연산 (Not 연산)
- bit shift 연산자 : 비트를 이동하는 연산자
- << : 왼쪽이동
- A << B 형태이며 A는 이동할 숫자, B는 이동 횟수를 나타낸다.
- 숫자 A를 왼쪽으로 B만큼 이동시킨 후 빈 공간은 0으로 채워준다.
- >> : 오른쪽 이동
- A >> B 형태로 왼쪽 이동과 같다.
- 숫자 A를 오른쪽으로 B만큼 이동시킨 후 빈 공간은 0으로 채우지만 A가 음수라면 1로 채워진다.
- >>> : 부호 상관 없는 (unsigned) 오른쪽 이동
- A >>> B 형태
- 부호가 상관 없기 때문에 음수를 이동시키더라도 빈 자리를 0으로 채운다.
- << : 왼쪽이동
- bitwise 연산자 : 두 개의 숫자를 비교하는 연산자
모든 참조 자료형에 + 연산을 하게 되면 해당 클래스의 toString() 메소드의 결과와 연산자 뒤의 문자열을 더한다.
형 변환 (Casting)
- 형 변환 : 서로 다른 타입 사이에 변환하는 작업
- 형 변환 시 기본 자료형과 참조 자료형 모두 괄호로 묶어주면 된다.
- 형 변환이 불가능한 경우
- boolean 타입
- 기본 자료형 <-> 참조 자료형
- 범위가 작은 타입 -> 큰 타입 형 변환 시 별도로 명시하지 않아도 된다. (자동 형 변환, 묵시적 형 변환)
- 작은 타입의 값을 큰 타입에 대입해도 문제가 발생하지 않는다.
- 범위가 큰 타입 -> 작은 타입 형 변환 시 () 소괄호 안에 범위가 작은 타입을 명시한다. (명시적 형 변환)
- 작은 타입의 범위를 벗어나는 경우 숫자 손실로 인해서 버그가 발생하고 생각하지도 못한 값이 나온다.
- 소수점 버림
- 오버 플로우
- 돈과 같이 민감하고 정확해야하는 문제에 대해서는 조심해야한다.
- 그럼에도 불구하고 위험을 감수하고 큰 타입에서 작은 타입으로 값을 대입해서 사용하기 위해서는 명시적인 형 변환이 필요한 것이다.
- 형 변환을 한다고 해서 큰 타입이 작은 타입으로 변경되는 것이 아니다.
- 큰 타입에서 읽은 값이 변경되는 것이기에 기존의 값은 그대로 변경되지 않고 유지된다.
- 작은 타입의 범위를 벗어나는 경우 숫자 손실로 인해서 버그가 발생하고 생각하지도 못한 값이 나온다.
오버 플로우(OverFlow) : 정수에 대한 산술 연산이 주어진 자릿수로 표시할 수 있는 범위를 벗어나는 숫자 값을 생성하려고 할 때 오버 플로우가 발생해 전혀 다른 숫자로 표현된다.
오버 플로우가 발생 시 보통 시계가 한 바퀴 돈 것처럼 다시 범위의 처음부터 시작한다.
int intValue = 0;
double doubleValue = 10.0;
intValue = doubleValue; // 큰 타입-> 작은 타입으로 값을 대입하므로 컴파일 에러가 발생한다.
intValue = (int)doubleValue; // 명시적 형 변환을 통해 컴파일 에러가 발생하지 않는다.
- 큰 타입에서 작은 타입으로 값을 대입할 때는 명시적 형 변환이 무조건 필요하다!!
- 그렇지 않으면 컴파일 에러가 발생한다.
- 작은 타입 변수 = (작은 타입) 큰 타입 변수; 와 같이 형 변환이 필요하다.
- 자바 계산에서 유의할 점
- 같은 타입끼리의 계산은 같은 타입의 결과를 낸다
- ex) int + int = int, long + long = long
- 서로 다른 타입끼리의 계산은 큰 범위의 타입으로 자동 형 변환이 일어난다.
- ex) int + long = long, long + double = double
- 같은 타입끼리의 계산은 같은 타입의 결과를 낸다
double doubleValue = 3 / 2; // 1.0
/* 계산 과정
double doubleValue = int / int = int;
double doubleValue = 1;
double doubleValue = (double) 1;
double doubleValue = 1.0; */
double doubleValue2 = 3.0 / 2; // 1.5
/* 계산 과정
큰 범위의 double로 작은 범위의 int는 자동 형 변환이 된다.
double doubleValue = double / (double)int = double;
double doubleValue2 = 1.5;
double doubleValue = (double) 1.5;
double doubleValue = 1.0; */
- 나누기를 하는 경우에 double 타입에 값을 할당한다고 해도 int / int = int 이므로 int 값이 자동 형 변환되어 double 타입 변수에 대입되게 되기에 예상치 못한 값이 나온다.
- double 타입에 값을 대입할 때 double / int, int / double, double / double로 한다면 double로 값이 자동 형 변환 되어 나오게 되고 그 값이 double 타입 변수에 대입되므로 문제가 발생하지 않는다.
간단 내용 정리
1. 값을 할당할 때 사용하는 연산자의 기호는 무엇인가요?
ㅡ> 할당 연산자는 =, 좌측에는 할당 받을 변수 / 우측에는 할당할 값을 적는다.
2. 기본적인 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지를 계산할 때 사용하는 연산자의 기호는 순서대로 각각 무엇인가요?
ㅡ> 순서대로 +, -, *, /, % 연산자를 사용하면 된다.
3. += 는 무엇을 할 때 사용하는 연산자 인가요?
ㅡ> += 는 기존 값에 우측 항의 값을 더할 때 사용한다.
4. 연산의 순서를 모르거나 확실히 하고 싶을 때에는 어떤 기호를 사용해야 하나요?
ㅡ> 소괄호()를 사용해 우선 순위를 확실하게 해줄 수 있다.
5. ==와 !=의 차이는 무엇인가요?
ㅡ> == 는 값이 같은지, !=는 값이 다른지를 확인하는 boolean 타입을 결과로 하는 연산자이다.
6. <와 <=의 차이는 무엇인가요?
ㅡ> 모두 크기를 비교하는 연산자, 차이는 우측항의 값이 포함되는 여부다. =이 있는 연산자는 우측항의 값을 포함한다.
7. ! 연산자는 어떤 타입에 사용 할 수 있나요?
ㅡ> ! 연산자는 무조건 boolean 타입에만 사용할 수 있다. 해당 결과의 반대 값으로 변환한다.
8. ? : 로 표시하는 삼항 연산자의 ?와 : 뒤에 명시해 주는 값은 무엇을 의미 하나요?
ㅡ> ? 뒤에는 조건이 true일 경우의 값을, : 뒤에 false일 경우의 값을 지정한다.
9. 자바는 형변환을 한다고 했는데, short의 값을 long에 할당할 때에는 어떤 것을 해 주어야 하나요?
ㅡ> casting을 해 줄 필요가 없다.
10. 반대로 long값을 short에 할당할 때에는 어떤 것을 해 주어야 하나요?
ㅡ> casting을 해줘야 한다. 소괄호() 안에 범위가 작은 타입을 명시해줘야한다.
11. 위의 두 문제에서 어떤 경우가 기존 값이 사라지고, 엉뚱한 값으로 바뀔 수 있나요?
ㅡ> 범위가 큰 타입에서 작은 타입으로의 형 변환이 일어나는 경우.
출처: 이상민, <자바의 신 VOL.1> 로드북
'Java > 자바의 신 VOL.1' 카테고리의 다른 글
07. 여러 데이터를 하나에 넣을 수는 없을까요? (0) | 2024.06.20 |
---|---|
06. 제가 조건을 좀 따져요 (1) | 2024.06.19 |
04. 정보를 어디에 넣고 싶은데 (0) | 2024.06.18 |
03. 자바를 제대로 알려면 객체가 무엇인지를 알아야 해요 (0) | 2024.06.18 |
02. Hello God Of Java (0) | 2024.06.18 |