프로그램에서 데이터를 처리하여 결과를 산출하는 것을 연산(Operations)이라고 한다.


- 연산자(Operator) : 어떤 연산을 나타내는 표시나 기호 

- 피연산자(Operand) : 해당 연산식에서 연산되는 데이터

- 연산식(Expressions) : 연산자와 피연산자를 이용하여 연산의 과정을 표현한 것



* 연산자의 종류


 유형

연산자

피연산자 수 

기능

예시 

과값

산술 연산자 

+, -, *, /, % 

2개 (이항)

사칙연산과 나머지 계산 

z = x + y

 숫자

부호 연산자

+, - 

1개 (단항) 

양수 및 음수의 표현

x = -x

 숫자

문자열 연산자

2개 (이항) 

두 문자열을 연결 

 "안녕" + "하세요"

문자열

대입 연산자

=, +=, -=, *=, /=

%=, &=, ^=, |=, <<=, >>= 

2개 (이항) 

좌변의 변수에 우변의 값을 대입

x += 1  (x = x + 1)

x &= y  (x = x & y)

 

증감 연산자

++, -- 

1개 (단항)

1만큼 증가(++) 또는 감소(--) 

++x (선증가 후연산)

x++ (선연산 후증가)

숫자 

비교 연산자 

==, !=, <, >, >=, <=, instanceof 

2개 (이항) 

값의 비교

x >= y  (x가 y보다 크거나 같은가)

boolean - true/false

논리 연산자 

!, &, |, &&, || 

단항 또는 이항

NOT(!), AND(&, &&), OR(|, ||) 연산

밑에 추가 설명

boolean - true/false

조건 연산자

(조건식) ? T : F 

3개 (삼항) 

조건식이 참이면 T, 거짓이면 F

(x > y) ? x : y

 

비트 연산자 

~, &, |, ^ 

단항 또는 이항

비트 XOR, AND, OR, NOT 연산 

밑에 추가 설명

숫자, boolean 

쉬프트 연산자 

<<, >>, >>> 

2개 (이항) 

비트 이동 연산자로 비트를 좌측, 우측으로 밀어서 이동 

밑에 추가 설명

숫자 




▶ 산술 연산자


1. 자바는 리터럴 간의 연산은 타입 변환 없이 계산한다.

ex) char c = 'A' + 1; // c에는 유니코드 66인 'B' 가 저장된다.

(But.) char c2 = c + 1; // c는 int타입으로 변환되고 1과 연산되므로 산출 타입은 int이다. 따라서 컴파일 에러.

위의 경우, c를 int타입으로 캐스팅(Casting)해서 char 타입으로 변환해야 한다.


2. 오버플로우 탐지 : 산출 타입(Type)으로 표현할 수 없는 값이 산출되면, 오버플로우가 발생하고 쓰레기값을 얻는다.


3. / 또는 % 연산자 사용 시 우측 피연산자는 0을 사용할 수 없다. 0으로 나누게 되면 예외(ArithmeticException)가 발생한다. 또한 실수 타입인 0.0 또는 0.0f로 나누면 예외가 발생하지 않고, / 연산의 결과는 Infinity(무한대) 값을 가지며, % 연산의 결과는 NaN(Not a Number)을 가진다. 이 때는 데이터가 엉망이 되므로 그 다음의 연산을 수행해선 안된다. 따라서 부동소수점(실수)을 입력받을 때 입력값의 NaN 여부를 조사하고 연산을 수행해야 한다.

(But.) NaN인지 조사할 때 == 연산자를 사용해선 안되며, Double.isNaN() 을 사용해야 한다. 그 이유는 NaN는 != 연산자를 제외한 모든 비교 연산자에서 false를 리턴하기 때문이다.



▶ 비교 연산자


1. 비교 연산자에서는 연산을 수행하기 전에 타입 변환을 통해 피연산자의 타입을 일치시킨다.


2. 예외 : 0.2 == 0.2f 의 경우 이진 포맷의 가수를 사용하는 모든 부동소수점 타입은 0.1을 정확히 표현할 수 없기 때문에 0.1f는 0.1의 근사값으로 나타나므로 피연산자를 모두 float 타입으로 강제 타입 변환한 후 비교 연산을 수행해야 한다.


3. String 객체의 문자열 비교할 때는 ==가 아닌 equlas() 메소드를 사용해야 한다. == 사용 시 객체의 번지값을 비교하므로 번지가 다른 객체일 경우 같은 문자열 상수라도 false가 나온다.



▶ 논리 연산자


1. AND (논리곱) - && 또는 & : 피연산자 모두 true일 경우 연산 결과로 true를 반환한다.


2. OR (논리합) - || 또는 | : 피연산자 중 적어도 하나가 true일 경우 연산 결과로 true를 반환한다.


3. XOR (배타적 논리합) - ^ : 피연산자가 하나는 true이고 다른 게 false일 경우에만 연산 결과는 true를 반환한다. (서로 다를 경우)


4. NOT (논리부정) - ! : 피연산자의 논리값을 바꾼다. true 이면 false ,  false이면 true로 변환한다.



▶ 비트 연산자


1. 비트 연산자는 데이터를 비트(bit) 단위로 연산한다.


2. 비트 반전 연산자, 논리 부정(~)

# 피연산자를 이진수로 표현했을 때, 0을 1로, 1은 0으로 반전한다.

# 정수 타입(byte, short, int, long)의 연산자에게만 사용된다.

# 연산 후, 부호 비트인 최상위 비트를 포함해서 모든 비트가 반전된다.

# 비트 반전 연산자의 산출 타입은 int 타입이다.

# 비트 반전 연산자의 산출값에 1을 더하면 부호가 반대인 정수를 얻는다.


3. 논리곱(AND) - & : 두 비트 모두 1일 경우에만 연산 결과가 1이 된다.


4. 논리합(OR) - | : 두 비트 중 적어도 하나가 1이면 연산 결과는 1이 된다.


5. 배타적논리합(XOR) - ^ : 두 비트 중 하나는 1이고 다른 하나가 0일 경우 연산 결과는 1이 된다.



▶ 쉬프트 연산자(비트 이동 연산자)


1. a << b : 정수 a를 이진법으로 표현했을 때, 각 비트를 b만큼 왼쪽으로 이동시키고 빈자리는 0으로 채워진다.


2. a >> b : 정수 a를 이진법으로 표현했을 때, 각 비트를 b만큼 오른쪽로 이동시키고 빈자리는 정수 a의 최상위 부호 비트와 같은 값으로 채워진다.


3. a >>> b : 정수 a의 각 비트를 b만큼 오른쪽으로 이동시키고 빈자리는 0으로 채워진다.



* 연산 방향 및 우선 순위


 연산자

연산 방향

우선 순위 

증감(++, --), 부호(+, -), 비트(~), 논리(!) 

← 

 높음












낮음

산술(*, /, %)

산술(+, -)

쉬프트(<<, >>, >>>) 

비교(<, >, <=, >=, instanceof) 

비교(==, !=) 

논리(&)

논리(^)

논리(|) 

논리(&&) 

논리(||) 

조건( ? : ) 

대입(=, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=, >>>=)






타입 변환 : 데이터 타입을 다른 데이터 타입으로 바꾸는 것.



- 자동 타입 변환(Promotion)


 : 프로그램 실행 중에 자동으로 타입 변환이 일어나는 것을 의미한다.



큰 크기의 타입 ← 작은 크기의 타입


* 여기서 크기는 사용하는 메모리 크기(바이트 수)를 말한다.


즉, byte ▶ short  int  long  float  double 순서 또는 char  int 순서로 자동 타입 변환이 일어난다.


참고로 long(8 byte)이 float(4 byte)보다 크지만 표현할 수 있는 숫자의 범위가 float이 더 크기때문에 float이 더 큰 타입으로 표시된 것이다. 또한, 정수 타입이 실수 타입으로 변환될 경우 자연수 뒤에 소수점과 소수점이하가 표시된다.


int i = 200;

double d = i; // 이때 d는 200.0이 된다. 



자동 타입 변환에서는 딱 한 가지 예외가 있는데, char는 2 바이트의 크기를 가지지만 char의 범위는 0~65535이므로 음수가 저장될 수없다. 즉, 음수가 저장될 수 있는 byte 타입은 char 타입으로 자동 변환시킬 수 없다.




Q) 데이터 손실 유무는 ?


A) 변환 이전의 값은 변환 이후에도 그대로 보존된다. 쉽게 말하자면 작은 양동이의 물을 큰 양동이로 옮긴다고 해도 물의 양은 변하지 않는 것과 같은 것이다.




- 강제 타입 변환(Casting)


 : 큰 데이터 타입을 작은 데이터 타입으로 쪼개어 강제로 저장하는 것을 의미한다.



큰 크기의 타입 → 작은 크기의 타입



즉, byte ◀ short  int  long ◀ float ◀ double 순서 또는 char ◀ int 순서로 강제 타입 변환이 일어난다.



# 사용 방법


작은 크기 타입 = (작은 크기 타입) 큰 크기 타입;


int i = 214748364;

byte b = (byte) i;


위의 경우 끝의 1 byte만 byte 타입 변수에 담게 된다. 즉, 변환되어질 데이터(작은 크기의 타입)보다 큰 것을 강제 타입 변환을 할 때 기존의 값은 보존되지 않는다.



# 주의 사항


int -> float으로 강제 타입 변환을 할 때,


float : 부호(1비트) + 지수(8비트) + 가수(32비트)


로 구성되어 있기 때문에 int 값이 123456780 처럼 가수 23비트로 표현불가능한 숫자일 경우 근사값으로 변환된다. 이 점은 정밀도 손실을 발생시키기 때문에 모든 int값을 안전하게 실수 타입으로 변환시키려면 double 타입을 사용하는 것이 현명하다. 


double : 부호(1비트) + 지수(11비트) + 가수(52비트)


그 이유는 int값은 4바이트 = 32비트 이므로 double의 가수 52비트보다 항상 작기 때문에 정밀도 손실없이 변환이 가능하다.



헷갈린다면 다른 타입으로 강제 타입 변환 시 변환될 타입(작은 크기의 타입)의 최대값과 최소값을 넘어가는지 확인하면 된다.

아래는 기본타입의 최대값과 최소값을 나타낸 표이다.



 기본 타입

최대값 상수 

최소값 상수 

byte 

Byte.MAX_VALUE 

Byte.MIN_VALUE 

short

Short.MAX_VALUE 

Short.MIN_VALUE 

int 

Integer.MAX_VALUE 

Integer.MIN_VALUE 

long 

Long.MAX_VALUE 

Long.MIN_VALUE  

float 

Float.MAX_VALUE 

Float.MIN_VALUE 

double 

Double.MAX_VALUE

 Double.MIN_VALUE 




자바의 실행 과정은 컴파일러에서 바이트 코드가 생성되고 자바 가상 기계를 통해 바이트 코드가 기계어로 변환된다.


Q) 왜 컴파일러와 자바 가상 기계라는 두 단계를 거치는 걸까?


A) 사용자가 모든 컴퓨터에서 응용 프로그램들을 다시 컴파일하지 않고 실행되게 하기 위해서이다.


Q) 자바 가상 기계는 별도로 설치해야 되는가?


A) 자바 가상 기계는 실제로 존재하는 컴퓨터가 아니라 가상 컴퓨터를 시뮬레이션하는 소프트웨어이다. 자바 가상 기계를 이용하면 하드웨어와 운영 체제를 프로그램으로부터 숨길 수 있다. 또한, 자바 가상 기계는 자바 컴파일러가 코드를 생성할 대상이 되는 추상화된 기계의 명세에 의하여 소프트웨어로 작성된다.


대부분의 프로그래밍 언어의 경우, 컴파일러에 의해 소스 코드 -> 기계어로 변환되어야 컴퓨터에서 실행할 수 있다. 그러나 자바 컴파일러는 특정한 컴퓨터를 위한 코드를 바로 생성하는 것이 아니라 자바 가상 기계(Java virtual machine)를 위한 바이트 코드(byte code)를 생성한다.


즉,

  

위와 같은 형태를 띄게 된다. 아래는 자바 실행 과정이다.



Hello.java (원본 파일)

Compiler

   Hello.class (바이트 코드)  

JVM 

  Hello(내용물)



Q) 자바 플랫폼(Platform)의 구성요소는 자바 가상 기계만 있는가?


A) 자바 플랫폼이란 프로그램이 실행되는 하드웨어(Hardware)나 소프트웨어(Software)의 환경을 뜻한다. 자바 플랫폼은 두 가지의 요소로 이루어져 있다.


- 자바 가상 기계 (JVM : Java Virtual Machine)

- 자바 응용 프로그래밍 인터페이스(API: Application Programming Interface)



Q) API란 무엇을 의미하는가?


A) 운영 체제(OS)나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 하여 응용 프로그램에서 사용할 수 있도록 만든 인터페이스이다. 파일 제어, 창 제어, 화상 처리, 문자 제어 등이 있다.



+ Recent posts