728x90
SMALL
'자바의 정석 3rd Edition'을 공부하며 정리한 내용입니다.
1. 연산자(Operator)
1.1 연산자와 피연산자
- 연산자(operator): 연산을 수행하는 기호 (+,-.*,/ 등)
- 피연산자(operand): 연산자의 작업 대상(변수, 상수, 리터럴, 수식)
- 연산자는 피연산자로 연산을 수행하고 나면 항상 결과값을 반환
- 대입 연산자는 우변의 값을 좌변에 저장하고 저장된 값을 연산결과로 반환
1.2 식과 대입연산자
- 식: 연산자와 피연산자를 조합하여 계산하고자하는 바를 표현한 것
- 식을 평가(evaluation)한다: 식을 계산하여 결과를 얻는 것
- 하나의 식을 평가하면, 단 하나의 결과를 얻음
- 대입 연산자 =를 사용해 변수와 같이 값을 저장할 수 있는 공간에 결과를 저장
- 식의 평가결과를 다른 곳에 사용하지 않을 것이라면 변수에 저장하지 않고 println 메서드의 괄호 안에 직접 식을 써도 됨
1.3 연산자의 종류
종류 | 연산자 | 설명 |
---|---|---|
산술 연산자 | + - * / % << >> | 사칙 연산(+,-,*,/)과 나머지 연산(%) |
비교 연산자 | > < >= <= == != | 크고 작음과 같고 다름을 비교 |
대입 연산자 | = | 우변의 값을 좌변에 저장 |
기타 | (type) ?: instanceof | 형변환 연산자, 삼항 연산자, instanceof 연산자 |
- 논리 연산자: &&, ||, !, &, |, ^, ~ (AND와 OR으로 조건을 연결)
1.4 연산자의 우선순위와 결합규칙
1. 주의해야 할 연산자 우선순위의 예와 설명
식 | 설명 |
---|---|
x << 2 + 1 |
쉬프트 연산자(<<)는 덧셈 연산자보다 우선순위가 낮음. 'x<<(2+1) '과 같은 식 |
data & 0xFF == 0 |
비트 연산자(&)는 비교 연산자(==)보다 우선순위가 낮으므로 비교연산 후에 비트연산 수행. 'data & (0xFF == 0) '와 같은 식 |
- 논리 연산자 중에서 AND를 의미하는 '&', '&&'가 OR를 의미하는 '|', '||'보다 우선순위가 높음. 수식에 AND와 OR가 함께 사용되는 경우 괄호를 사용해 우선순위를 명확히 하는 것이 좋음
2. 연산자의 결합규칙
- 대부분 왼쪽에서 오른쪽의 순서로 연산을 수행
- 단항 연산자와 대입 연산자만 반대로 오른쪽에서 왼쪽의 순서로 연산을 수행
3. 연산자 우선순위 정리
- 산순 > 비교 > 논리 > 대입. 대입은 제일 마지막에 수행됨
- 단항 > 이항 > 삼항. 단항 연산자의 우선순위가 이항 연산자보다 높음
- 단항 연산자와 대입 연산자를 제외한 모든 연산의 진행방향은 왼쪽에서 오른쪽
1.5 산술 변환(usual arithmetic conversion)
- 이항 연산자는 두 피연산자의 타입이 일치해야 연산이 가능하므로 피연산자의 타입이 다를 경우 먼저 형변환 연산자로 타입을 일치시켜야 함
- 두 피연산자의 타입 중 더 큰 타입으로 일치시킴
- 작은 타입에서 큰 타입으로 형변환하는 경우 자동적으로 형변환되므로 형변환 연산자를 생략할 수 있음
- 산술 변환: 연산 전에 피연산자 타입의 일치를 위해 자동 형변환되는 것. 이항 연산과 단항 연산에서 수행
- 쉬프트 연산자, 증감 연산자에서는 산술 변환이 일어나지 않음
- 규칙 1. 두 피연산자의 타입을 같게 일치시킴(큰 타입으로 일치)
- 규칙 2. 피연산자의 타입이 int보다 작은 타입이면 int로 변환
- 연산 결과의 타입은 피연산자의 타입과 일치
2. 단항 연산자
2.1 증감 연산자 ++ --
- 증감 연산자: 피연산자에 저장된 값을 1 증가 또는 감소시킴
- 피연산자로 정수, 실수 모두 가능하지만 상수는 값을 변경할 수 없으므로 불가능
- 산술 변환에 의한 자동 형변환이 발생하지 않고, 연산결과의 타입은 피연산자의 타입과 같음
- 일반적으로 단항 연산자는 피연산자의 왼쪽에 위치하지만 '++', '--'는 양쪽 모두 가능
타입|설명|사용예
---|---|
전위형(prefix)|값이 참조되기 전에 증가시킴. 변수의 값을 먼저 증가시킨 후에 읽어옴| j = ++i;
후위형(postfix)|값이 참조된 후에 증가시킴. 변수의 값을 먼저 읽어온 후에 값을 증가|j=i++;
- '++i;', 'i++;'처럼 증감 연산자가 수식이나 메서드 호출에 포함되지 않고 독립적인 하나의 문장으로 쓰인 경우 전위형과 후위형 차이는 없음
2.2 부호 연산자 + -
- 부호 연산자 '-': 피연산자의 부호를 반대로 변경한 결과를 반환
- 피연산자가 음수면 양수, 양수면 음수가 연산의 결과가 됨
- boolean형과 char형을 제외한 기본형에만 사용 가능
3. 산술 연산자
3.1 사칙 연산자 + - * /
1. 숫자에서의 사칙 연산
- 곱셈, 나눗셈, 나머지 연산자가 덧셈, 뺄셈 연산자보다 우선순위가 높아 먼저 처리
- 피연산자가 정수형인 경우, 나누는 수로 0을 사용할 수 없음
- 0으로 나눌 경우 ArithmeticException 발생
- 부동 소수점값인 0.0f, 0.0d로 나누는 것은 가능하지만 결과는 Infinity
- 나누기 연산자의 두 피연산자가 모두 int 타입인 경우 연산결과에 소수점이 있을 경우 반올림하지 않고 버려짐
- 올바른 연산결과를 얻기 위해서는 두 피연산자 중 한 쪽을 실수형으로 형변환해야 함
byte a = 10;
byte b = 20;
byte c = a + b; // byte c = (byte)(a+b);로 변경해주어야 에러 발생 X
System.out.println(c);
- 위의 코드 같은 경우 컴파일하면 에러 발생
- a와 b는 모두 int형보다 작은 byte형이기 때문에 +는 이 두 개의 피연산자들의 자료형을 int형으로 변환한 다음 연산 수행. 따라서 a+b의 결과값은 int형
- 4byte 값을 1byte에 저장하려했기 때문에 에러 발생
- 크기가 큰 자료형의 값을 작은 자료형의 변수에 저장하려면 명시적으로 형변환 연산자를 사용해서 변환해주어야 함
- 수식에 변수가 들어가 있는 경우 컴파일러가 미리 계산할 수 없으므로 형변환을 해주어야 함
2. 문자에서의 사칙 연산
- 문자는 실제로 해당 문자의 유니코드(부호없는 정수)로 바뀌어 저장되므로 문자간의 사칙연산은 정수간의 연산과 동일
- 문자간의 뺄셈을 하는 경우가 대부분
- 문자 '2'를 숫자로 변환하려면 문자 '0'dmf Qownaus ehla
- 문자 '2'의 유니코드는 50이고 문자 '0'은 48이기 때문
char c2 = 'a' + 1; // 출력값: b
- 오류 발생 X
- 이항 연산자는 int보다 작은 타입의 피연산자를 int로 자동 형변환한다고 했는데
char c2 = (char) ('a'+1)
처럼 형변환해주지 않고도 문제가 없는 이유- 리터럴 간의 연산이기 때문
- 상수 또는 리터럴 간의 연산은 실행 과정동안 변하는 값이 아니기 때문에 컴파일 시에 컴파일러가 계산해서 그 결과로 대체함으로써 코드를 효율적으로 만듦
- 컴파일러가 미리 덧셈연산을 수행해 실생 시에는 덧셈 연산이 수행되지 않음
3. 소문자를 대문자로 변경하는 코드
- 대문자와 소문자 간의 코드값 차이는 10진수로 32
char lowerCase = 'a'; char upperCase = (char) (lowerCase - 32);
- 대문자를 소문자로 변환하려면 32를 더해주면 됨
- char형과 int형 간의 뺄셈 결과는 int 형이므로 연산 후 char형으로 다시 형변환해야 함
4. 반올림하는 방법
- 'int / int'를 수행하면 소수점을 버린 결과가 나옴
- 반올림을 하고 싶다면
Math.round()
를 사용double pi = 3.141592; Math.round(pi * 1000) => Math.round(3141.592) => 3142
3.2 나머지 연산자 %
- 왼쪽의 피연산자를 오른쪽 피연산자로 나누고 난 나머지 값을 결과로 반환하는 연산자
- 나눗셈에서처럼 오른쪽 피연산자로 0을 사용할 수 없지만 음수는 허용
- 음수를 사용할 경우 부호는 무시되므로 결과는 음수의 절대값으로 나눈 나머지와 같음
- 짝수, 홀수 또는 배수 검사 등에 주로 사용
- 피연산자의 부호를 모두 무시하고 나머지 연산을 한 결과에 왼쪽 피연산자의 부호를 붙이면 됨
4. 비교 연산자
- 조건문, 반복문의 조건식에 사용. 연산 결과는 true, false 둘 중 하나
- 비교 연산자도 이항 연산자이므로 비교하는 피연산자의 타입이 다를 경우 자료형의 볌위가 큰 쪽으로 자동 형변환하여 피연산자의 타입을 일치시킨 후에 비교
4.1 대소비교 연산자 < > <= >=
- 기본형 중에서 boolean을 제외한 나머지 자료형에 모두 사용 가능하지만 참조형에는 사용 불가
4.2 등가비교 연산자 == !=
1. 숫자 비교
- 기본형과 참조형에 모두 사용 가능
- 기본형의 경우 변수에 저장되어 있는 값이 같은지를 알 수 있음
- 참조형의 경우 객체의 주소값을 저장하기 때문에 두 개의 피연산자(참조변수)가 같은 객체를 가리키고 있는지 확인 가능
- 기본형과 참조형은 서로 형변환이 불가능하므로 등가비교 연산자로 기본형과 참조형을 비교할 수는 없음
- float 타입과 double 타입의 값을 비교하려면 double 타입의 값을 float 타입으로 형변환한 다음 비교해야 올바른 결과를 얻을 수 있음
2. 문자열 비교
- 두 문자열을 비교할 때는 비교 연산자 '==' 대신
equals()
라는 메서드를 사용해야 함- 비교 연산자는 두 문자열이 완전히 같은 것인지를 비교할 뿐, 문자열의 내용이 같은지 비교하기 위해서는
equals()
를 사용해야 함 - 비교 연산자의 경우 내용이 같지만 다른 객체일 경우 fasle를 반환
equals()
의 경우 객체는 다르지만 내용이 같다면 true를 반환
- 비교 연산자는 두 문자열이 완전히 같은 것인지를 비교할 뿐, 문자열의 내용이 같은지 비교하기 위해서는
- 대소문자를 구별하지 않고 비교하고 싶다면
equalsIgnoreCase()
를 사용
5. 논리 연산자
- 둘 이상의 조건을 AND나 OR으로 연결하여 하나의 식으로 표현할 수 있게 해줌
5.1 논리 연산자 - &&, ||, !
- 논리 연산자는 피연산자로 boolean형 또는 boolean형 값을 결과로 하는 조건식만을 혀용
- || (OR 결합): 피연산자 중 어느 한쪽만 true이면 true를 결과로 얻음
- && (AND 결합): 피연산자 양쪽 모두 true이어야 true를 결과로 얻음
- ! (논리 부정 연산자): 피연산자가 true이면 false를, false이면 true를 결과로 반환
- 어떤 값에 논리 부정 연산자를 반복적으로 적용하면 참과 거짓이 차례로 반복됨
- 토글 버튼(toggle button)을 논리적으로 구현 가능
효율적인 연산(short circuit evaluation)
- OR 연산의 경우, 두 피연산자 중 어느 한 쪽만 참이어도 전체 연산결과가 참이므로 죄측 피연산자가 true이면 우측 피연산자의 값으 평가하지 않음
- AND 연산의 경우, 어느 한쪽만 false이어도 전체 연산결과가 false이므로 좌측 피연산자가 false이면 우측 피연산자는 평가하지 않음
- 같은 조건식이라도 피연산자의 위치에 따라 연산속도가 달라질 수 있음
- OR 연산의 경우 연산결과가 참일 확률이 높은 피연산자를 연산자의 왼쪽에 놓아야 더 빠른 연산결과를 얻을 수 있음
5.2 비트 연산자 & | ^ ~ << >>
- 피연산자를 비트단위로 논리 연산
- 피연산자는 실수는 혀용하지 않고 정수(문자 포함)만 허용
toBinaryString()
: 비트연산의 결과를 2진수로 출력
비트 연산자 종류
- | (OR 연산자): 피연산자 중 한 쪽의 값이 1이면, 1을 결과로 얻고 그 외에는 0을 얻음
- 특정 비트의 값을 변경할 대 사용
- & (AND 연산자): 피연산자 양 쪽이 모두 1이어야 1을 결과로 얻고 그 외에는 0을 얻음
- 특정 비트의 값을 뽑아낼 때 사용
- ^ (XOR 연산자): 피연산자의 값이 서로 다를 때만 1을 얻고 그 외에는 0을 얻음
- 같은 값으로 두고 XOR 연산을 수행하면 원래의 값으로 돌아오는 특징이 있어 간단한 암호화에 사용
- ~(비트 전환 연산자): 피연산자를 2진수로 표현했을 때, 0은 1로, 1은 0으로 바꿈
- 비트 전환되고 나면, 부호있는 타입의 피연산자는 부호가 반대로 변경됨 => 피연산자의 1의 보수를 얻을 수 있음
- 양의 정수 p가 있을 때, p에 대한 음의 정수를 얻으려면 '
~p+1
'를 계산 - 음의 정수 p가 있을 때, p에 대한 양의 정수를 얻으려면 '
~(p-1)
'를 계산 - 부호 연산자 -를 사용하면 간단하게 변환할 수 있음
~~p
: 변수 p에 두 번의 비트 전환 연산을 적용. 원래 값과 같지만 연산 결과의 타입은 byte가 아니라 int
- 쉬프트 연산자 << >>: 피연산자의 각 자리를 오른쪽(>>) 또는 왼쪽(<<)으로 이동시키는 연산자
- 자리 이동으로 저장범위를 벗어난 값들은 버려지고 빈자리는 0으로 채움
- '<<' 연산자의 경우, 피연산자의 부호에 상관없이 각 자리를 왼쪽으로 이동시키며 빈칸을 0으로 채우면 됨
x << n
은 $x * 2^n$의 결과와 같음
- '>>' 연산자의 경우, 오른쪽으로 이동시키기 때문에 부호있는 정수는 부호를 유지하기 위해 왼쪽 피연산자가 음수인 경우 빈자리를 1로 채움. 양수일 경우 0으로 채움
x >> n
은 $x / 2^n$의 결과와 같음
- 좌측 피연산자는 산술변환이 적용되어 int보다 작은 타입은 int타입으로 자동 변환되고 연산결과도 int타입이 됨
- 피연산자의 타입을 일치시킬 필요가 없기 때문에 우측 피연산자에는 산술변환이 적용되지 않음
- 쉬프트 연산자를 사용하는 것이 산술 연산자를 사용하는 것보다 더 빠름. 하지만 코드의 가독성이 떨어지기 때문에 곱셈 또는 나눗셈 연산자를 주로 사용하고, 빠른 실행속도가 요구되어지는 곳만 쉬프트 연산자를 사용하는 것이 좋음
6. 그 외의 연산자
6.1 조건 연산자 ? :
- 조건식, 식1, 식2 세 개의 피연산자를 필요로 하는 삼항 연산자이며, 삼항 연산자는 조건 연산자 하나
조건식 ? 식1 : 식2
- 조건식이 true이면 식1이, false면 식2가 연산 결과가 됨
- 조건 연산자는 조건문인 if문으로 바꿔쓸 수 있으며, if문 대신 조건 연산자를 사용하면 코드를 간단히 할 수 있음
- 조건 연산자를 중첩해서 사용하면 셋 이상 중의 하나를 결과로 얻을 수 있음
result = x > 0 ? 1 : (x==0 ? 0 : -1)
- x의 값이 양수면 1, 0이면 0, 음수면 -1의 결과가 나옴
- 조건 연산자의 식1과 식2, 두 피연산자의 타입이 다른 경우 산술 변환이 발생
6.2 대입 연산자 = op=
- 변수와 같은 저장공간에 값 또는 수식의 연산결과를 저장하는데 사용
- 오른쪽 피연산자의 값을 왼쪽 피연산자에 저장하고 저장된 값을 연산 결과로 반환
- 연산자들 중 가장 낮은 우선순위를 가지기 때문에 식에서 제일 나중에 수행됨
1. lvalue와 rvalue
- 대입 연산자의 왼쪽 피연산자를 lvalue(left value), 오른쪽 피연산자를 rvalue(right value)라고 함
- rvalue는 변수뿐만 아니라 식이나 상수 등이 모두 가능하지만 lvalue는 변수처럼 값을 변경할 수 있는 것이어야 함
- 리터럴이나 상수같이 값 변경이 불가능한 것은 lvalue가 될 수 없음
2. 복합 대입 연산자
- 다른 연산자(op)와 결합해 'op='와 같은 방식으로 사용 가능
- 결합된 두 연산자는 반드시 공백없이 붙여 써야 함
Chapter 3 끝!!!
728x90
LIST
'Book > Java의 정석' 카테고리의 다른 글
[Chapter 6] 객체지향 프로그래밍 1_1 (0) | 2022.04.01 |
---|---|
[Chapter 5] 배열 (Array) (0) | 2022.04.01 |
[Chapter 4] 조건문과 반복문 (0) | 2022.04.01 |
[Chapter 2] 변수 (0) | 2022.04.01 |
[Chapter 1] 자바를 시작하기 전에 (0) | 2022.04.01 |
댓글