본문 바로가기
Programming

[Java의 정석] 제 3장 연산자 - 1.연산자, 2.단항연산자

by SyWORLD 2017. 6. 23.
반응형

** 단순히 공부를 위한 참고자료일 뿐입니다. **

** 현재 버전과 상이한 부분은 검색해주시길 바랍니다. **




1. 연산자(Operator)


연산자는 모든 프로그래밍언어에서 가장 기본적이면서도 중요한 요소이다. 각 연산자의 특징 과 수행결과, 그리고 우선순위에 대해서 아주 잘 알고 있어야 한다.
자바는 연산자의 대부분과 조건문과 반복문 등의 기본 구문을 C언어에서 가져왔다. 그 것이 C 언어를 배운 사람이 자바를 쉽게 배우는 이유이기도 하다.

하지만, 프로그래밍 언어를 처음 배우는 사람이 자바를 배우기 위해 C언어를 배울 필요는 없 다. 그 시간에 자바를 배우는 데 투자하는 것이 프로그래밍실력을 향상시키는데 더 도움이 되 기 때문이다.


[표3-1연산자의 종류와 우선순위]

[참고]instanceof연산자는 인스턴스의 타입을 알아내는데 사용되는 연산자이다. 후에 자세하 게 다룰 것이므로 이에 대한 설명은 생략하겠다.

위의 표에서 같은 줄에 있는 연산자들은 우선순위가 같다. 우선순위가 같은 연산자들 간에는 연산방향에 의해서 연산순서가 정해진다.

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


[참고]연산자가 연산을 하는데 필요로 하는 피연산자의 개수에 따라서 단항, 이항, 삼항 연산자 라고 부른다. 덧셈 연산자(+)는 두 개의 피연산자를 필요로 하므로 이항연산자이다. [참고]표3-1에서 산술연산자 중 단항연산자의 '(자료형)'은 형변환에 사용되는 캐스트 연산자

이다.

연 산의 진행방향을 설명하기위해 다음과 같은 두 개의 식을 예로 들어보자. 수식 3*4*5는 곱 셈연산자(*)의 연산방향이 왼쪽에서 오른쪽이므로 수식의 왼쪽에 있는 3*4가 먼저 계산되고, 그 다음 3*4의 연산결과인 12와 5의 곱셈을 수행한다.




대입연산자는 연산방향이 오른쪽에서 왼쪽으로 진행하므로, 수식 x=y=3의 경우 제일 오른쪽 에서부터 계산을 시작해서 왼쪽으로 진행해 나간다.
따라서, y=3이 가장 먼저 수행되어서 y에 3이 저장되며, 그 다음에 x=y가 수행되어 y에 저장되 어 있는 값이 다시 x에 저장되어 x 역시 y와 같은 값을 갖게 된다.

즉, x=y=3;은 아래 두 문장을 한 문장으로 줄여 쓴 것과 같다.

y=3; // 먼저 y에 3이 저장되고
x=y; // y에 저장되어 있는 값(3)이 x에 저장된다.

[Tip]연산우선순위가 확실하지 않을 경우에는 괄호를 사용하면 된다. 괄호 안의 계산식이 먼저 계산될 것이 확실하기 때문이다.

이제 위의 표에 나와 있는 연산자들을 하나씩 자세히 살펴보도록 하자.




2.1증감연산자 - ++, --

일반적으로 단항연산자는 피연산자의 오른쪽에 위치하지만, ++와 --연산자는 양쪽 모두 가능 하다. 연산자를 어느 위치에 놓는가에 따라서 연산결과가 달라질 수 있다.

++ : 피연산자(operand)의 값을 1 증가 시킨다. -- : 피연산자(operand)의 값을 1 감소 시킨다.

boolean형을 제외한 모든 기본형(Primitive Type) 변수에 사용 가능하며, 피연산자의 왼쪽에 사용하는 전위형과 오른쪽에 사용하는 후위형이 있다.

[예제3-1] OperatorEx1.java

class OperatorEx1 {
public static void main(String args[]) {

int i=5;
i++; // i=i+1과 같은 의미이다. ++i; 로 바꿔 써도 결과는 같다. System.out.println(i);
i=5; // 결과를 비교하기 위해 i값을 다시 5로 설정.
++i;
System.out.println(i);

} }

[실행결과]

6 6

i의 값을 증가시킨 후 출력하는데, 한번은 전위형(++i)을 사용했고, 또 한번은 후위형(i++)을 사용했다. 결과를 보면 두 번 모두 i의 초기값 5에서 1이 증가된 6이 출력됨을 알 수 있다.
이 경우에는 어떤 수식에 포함된 것이 아니라 단독적으로 사용된 것이기 때문에, 증감연산자 (++)를 피연산자의 오른쪽에 사용한 경우(i++)와 왼쪽에 사용한 경우(++i)의 차이가 전혀 없
다.

[참고] 증감연산자를 피연산자의 앞에 사용하는 것을 전위형(prefix)이라 하고, 피연산자 다음 에 사용하는 것을 후위형(postfix)이라고 한다.

그러나, 다른 수식에 포함되거나 함수의 매개변수로 쓰여진 경우, 즉 단독으로 사용되지 않은 경우 전위형과 후위형의 결과는 다르다.

[예제3-2] OperatorEx2.java

class OperatorEx2 {
public static void main(String args[]) {

int i=5;
int j=0;
j = i++;
System.out.println("j=i++; 실행 후, i=" + i +", j="+ j);

i=5; // 결과를 비교하기 위해, i와 j의 값을 다시 5와 0으로 변경 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


i의 값은 어느 경우에서나 1이 증가되어 6이 되지만 j의 값은 전위형과 후위형의 결과가 다르다 는 것을 알 수 있다.
전위형은 변수(피연산자)의 값을 먼저 증가시킨 후에 변수가 참조되는데 반해, 후위형은 변수 의 값이 먼저 참조된 후에 값이 증가된다.

따라서, j=i++;(후위형)에서는 i값인 5가 참조되어 j에 5가 저장된 후에 i가 증가한다. j=++i;(전위형)에서는 i가 5에서 6으로 먼저 증가한 다음에 참조되어 6이 j에 저장된다.

다음은 함수의 매개변수에 증감연산자가 사용된 예이다.

[예제3-3] OperatorEx3.java

class OperatorEx3 {
public static void main(String args[]) {

int i=5, j=5;
System.out.println(i++); System.out.println(++j); System.out.println("i = " + i + ", j = " +j);

} }

[실행결과]

5
6
i = 6, j = 6

i 는 값이 증가되기 전에 참조되므로 println메서드에 i에 저장된 값 5를 넘겨주고 나서 i의 값 이 증가하기 때문에 5가 출력되고, j의 경우 j에 저장된 값을 증가 시킨 후에 println메서드에 값을 넘겨주므로 6이 출력된다. 결과적으로는 i, j 모두 1씩 증가되어 6이 된다. 감소연산자(--)는 피연산자의 값을 1 감소시킨다는 것을 제외하고는 증가연산자와 동일하다.

[알아두면 좋아요] ++i 와 i= i+1의 비교

두 수식의 결과는 같지만, 실제로 연산이 수행되는 과정은 다르다. ++i가 i = i + 1보다 더 적 은 명령만으로 작업을 수행하기 때문에 더 빠르다. 그리고, ++i를 사용하면, 수식을 보다 더 간략히 할 수 있다.



위의 표에서는 i = i + 1과 ++i를 컴파일 했을 때 생성되는 클래스 파일(*.class)의 바이트코드 명령어를 비교한 것이다.

i = i + 1은 5개의 명령으로 이루어져 있지만, ++i는 단 2개의 명령으로 이루어져 있다.
같은 결과를 얻지만, i = i + 1에 비해 ++i가 훨씬 적은 명령만으로 수행된다는 것을 알 수 있 다. 그리고 덧셈연산자(+)는 필요에 따라 피연산자를 형변환하지만 증감연산자는 형변환 없이 피연산자의 값을 변경한다.




2.2 부호 연산자 - +, -

부호연산자는 피연산자의 부호를 변경하는데 사용되며, boolean형과 char형을 제외한 나머 지 기본형에 사용할 수 있다.
부호연산자 '+'의 경우는 피연산자에 양수 1을 곱한 결과를, 그리고 '-'의 경우에는 피연산자에 음수 1을 곱한 결과를 얻는다.

[예제3-4] OperatorEx4.java

class OperatorEx4 {

public static void main(String[] args) {

int i = -10; i = +i;

System.out.println(i); i=-10;
i = -i; System.out.println(i);

} }

[실행결과]

-10 10




2.3 비트전환 연산자 - ~

'~'는 정수형과 char형에만 사용될 수 있으며, 피연산자를 2진수로 표현했을 때, 0은 1로 1은 0으로 바꾼다. 그래서, 연산자 '~'에 의해 비트전환 되고 나면, 피연산자의 부호가 반대로 변경 된다.
[주의]byte, short, char형은 int형으로 변환된 후에 전환된다.

[예제3-5] OperatorEx5.java

class OperatorEx5 {

public static void main(String[] args) {

byte b = 10;
System.out.println("b = " + b ); System.out.println("~b = " + ~b); System.out.println("~b+1 = " + (~b+1));

} }

[실행결과]

b = 10
~b = -11 ~b+1 = -10


결과를 보면, 어떤 양의 정수에 대한 음의 정수를 얻으려면 어떻게 해야 하는 지를 알 수 있다. 양의 정수 b가 있을 때, b에 대한 음의 정수를 얻으려면, ~b + 1을 계산하면 된다. 이 사실을 통해서 -10을 2진수로 어떻게 표현할 수 있는지 알 수 있을 것이다.





먼저 10을 2진수로 표현한 다음 0은 1로, 1은 0으로 바꾸고 그 결과에 1을 더한다. 그러면 -10의 2진 표현을 얻을 수 있다.

[예제3-6] OperatorEx6.java

class OperatorEx6 {

// 다.

public static void main(String[] args) {

byte b = 10;
byte result =~b; // '~'연산의 결과가 int이기 때문에 byte형 변수에 저장할 수 없

byte result =(byte)~b; // 또는 int result = ~b;와 같이 해야 한다. System.out.println("b = " + b ); 

System.out.println("~b = " + result ); }

}

[실행결과]

b = 10 ~b = -11

연산자'~'는 피연산자의 타입이 int형 보다 작으면, int형으로 변환한 다음 연산을 하기 때문에 위의 예제에서는 byte형 변수 b가 int형으로 변환된 다음에 연산이 수행되어 연산결과가 int형 이 된다.
그래서 연산자'~'의 연산결과를 저장하기 위해서는 int형 변수에 담거나, 캐스트 연산자를 사 용해야한다.




2.4 논리부정 연산자 - !

이 연산자는 boolean형에만 사용할 수 있으며, true는 false로 false는 true로 변경한다. 조건 문과 반복문의 조건식에 사용되어 조건식을 보다 효율적으로 만들어 준다.
연산자 '!'를 이용해서 한번 누르면 켜지고, 다시 한번 누르면 꺼지는 TV의 전원버튼과 같은 토 글버튼(Toggle button)을 논리적으로 구현할 수 있다.

[예제3-7] OperatorEx7.java

class OperatorEx7 {
public static void main(String[] args) {

boolean power = false;
System.out.println(power);
power = !power; // power의 값이 false에서 true로 바뀐다. System.out.println(power);
power = !power; // power의 값이 true에서 false로 바뀐다. System.out.println(power);

} }

[실행결과]

false true false














반응형

댓글