linuxism 2012. 4. 19. 15:34

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의 곱셈을 수행한다. 

 <BR> 

대입연산자는 연산방향이 오른쪽에서 왼쪽으로 진행하므로, 수식 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. 단항연산자
  
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); 
      } 

[실행결과]



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); 
      } 

[실행결과]


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 

출처 - http://cafe.naver.com/javachobostudy