정수 - 100 4byte 100L 8byte
부동소수점(실수) - 3.14 8byte 3.14f 4byte
논리 - true false
문자 - ‘A’, ‘가’
문자열 - "ABC가각간”
int[] arr = new int[2];
[ ][ ] 2칸짜리 배열 생성
int[] arr = new int[3];
arr[2700] -> 2700번째메모리의미 -> [0][1][2]
ㄴ int 배열의 reference(참조) ㄴ int배열의 instance(실례)
/ * + - %(나눈 나머지)
값 + 값
값 = 피연산자 Operand : 리터럴, 변수 둘 다 올 수 있음
연산자 Opertor
둘이 같은 레벨일 경우 먼저 나온 연산자 우선
(괄호)사용해서 실행 순서를 바꿀 수 있음
괄호: ()
후위 연산자: a++, a--
전위 연산자: ++a, --a, 단항 연산자(+, -)
, /, %
+, -
비트이동 연산자: <<, >>, >>>
관계 연산자: <, >, <=, >=, instanceof
등위 연산자: ==, !=
&
^
|
논리 연산자 AND: &&
논리 연산자 OR: ||
삼항 연산자: (조건) ? 값1 : 값2 //조건이 true면 값1 false면 값2
할당 연산자: =, +=, -=, =, /=, %=, &=, ^=, |=, <<=, >>=, >>>=
byte x = 5;
byte y = 6;
리터럴 5, 6 - 4byte 정수값
정수 리터럴은 기본이 4바이트지만 byte변수에 저장하는 것은 허락
byte z = 5 + 6;
리터럴끼리 산술한 결과도 리터럴로 간주
그 결과값이 변수의 범위 내의 값이면 허락
z = x + y; //컴파일오류
자바의 정수 연산은 최소단위가 4byte
정수변수에 대해 산술연산 수행시 그 변수 값이 4byte보다 작다면(byte -1, short-2)
임시로 4byte메모리를 만들어 연산 수행함
즉 z = x + y 연산에서 임의의 4byte 메모리에 x와 y를 각각 담아 연산 수행
연산결과 4byte >> z 메모리 1byte
결과가 메모리보다 커서 컴파일 오류 발생하는 것
위의 식들은 하나라도 리터럴이 있어서 허락이 발생하는 것이고 변수끼리의 식에서는 허락이 발생하지 않아 컴파일 오류가 발생한다
=> 숫자를 다룰때는 메모리가 큰 int를 사용하는 것이 편리하다
모든 종류의 데이터에 모든 종류의 연산자를 사용할 수 있는건XX
Boolean type은 산술연산자 불가
문자열 type은 +를 문자열 연결 용도로만 사용가능
정수끼리의 논리는 불가능
연산을 수행한 후 결과값은 피연산자와 같은 타입
int + int -> 결과도 int
int x = 5, y = 2;
float z = x / y //2.0
이미 int끼리의 연산으로 5/2=2라는 결과가 나온 상태에서 z에 대입되므로 값은 2.0이 된다
원하는 값을 얻기 위해서는 형변환을 해주면서 연산을 해야함
z = (float)x / (float)y // 2.5
두 값을 계산했을 때 결과 메모리를 초과할 경우 값이 짤릴 수 있음
코드를 작성할 때 피연산자의 계산 결과가 피연산자의 메모리 크기를 벗어날 가능성이 있다면?
-> 처음부터 피연산자의 값을 더 큰 메모리에 담아서 연산을 수행
변수나 리터럴을 다른 타입의 값을 바꾸는 것
!! 원래 변수의 타입을 바꾸는 것이 아님
내부적으로 변수에 들어 있는 값을 꺼내 지정된 타입의 임시 메모리를 만들어 저장
자바의 최소 연산 단위는 int
int보다 작은 크기의 메모리 다룰 때 내부적으로 int로 자동형변환 수행 후 연산 수행
내부적으로 자동 형변환하는 것 = "암시적 형변환(implicit type conversion)"
byte + byte = int / short + short = int
byte + short = int / byte + int = int
int + long = long
long + float = float -> 8byte의 long이 float 처리되면서 데이터손실 발생
long + double = double
Boolean + int => 연산불가!
byte short -> int -> long -> float -> double
여러 연산자와 data type이 섞여있을 때 연산 우선순위따라 계산하는 순간에 형변환 일어남
!! 모든 값을 최종 결과타입으로 바꿔놓고 계산하지않음
저장하려는 메모리보다 더 큰 값일 경우
byte b;
b = 259;
//컴파일 오류 -> 명시적 형변환을 통해 값을 지정해줌
b = (byte)259;
총 4byte 결과값 중 앞의 3byte가 잘리고 마지막 1byte만 저장됨
System.out.println(b); //3
형변환 하더라도 값이 소실되지 않을 경우에만 실시하는 것을 권장
관계연산자 : <, <=, >, >=
등위연산자 : == 같음, != 다름
비교의 결과값은 true, false -> boolean값만 가능
Boolean r1 = a < b; //true or false
int r2 = a < b; //컴파일 오류
double d1 = 987.6543;
double d2 = 1.111111;
System.out.println((d1 + d2) == 988.765411); // false
부동소수점 값을 연산할 때 IEEE 754 명세에 따라 작업을 수행한다. 그 과정에 값의 왜곡 발생
CPU나 OS, JVM의 문제XX
IEEE 754 명세에 따라 부동소수점을 처리하는 모든 컴퓨터에서 발생하는 문제
소수점 뒤에 붙은 극소수의 값을 무시하면 된다.
=> JVM이 자동으로 처리하지 않는다.
=> 다음과 같이 개발자가 직접 처리해야 한다.
double EPSILON = 0.00001;
System.out.println(Math.abs((d1 + d2) - (x + y)) < EPSILON);
미세오차 EPSILON 설정해서 비교할 두 값의 차가 오차보다 작음을 비교해주면 0으로 간주해 대충 같다고 간주
=> 오차를 제거한 후 비교
=> 다만 계산 결과를 절대값으로 만든 후에 오차 이하의 값인지 비교하라!
&& AND
|| OR
! NOT
^ XOR : 두 개의 값이 다를 때 true 1/ 같을때 false 0
and 연산자의 경우엔 둘 중에 하나라도 false면 false
때문에 앞의 논리값이 false면 이미 결과값이 false임을 알 수 있음
or 연산자의 경우엔 하나라도 true면 결과값도 true
때문에 이미 앞의 논리값이 true면 뒤의 논리값까지 보지 않고도 결과값이 true임을 알 수 있음
이렇게 앞의 논리값으로 결과를 예측할 수 있으면 뒤의 논리값까지 수행하지 않는 것이 &&와 || 연산자
그래도 끝까지 연산을 수행하는 것이 &와 |
&&, ||
&, |
boolean a = false;
boolean b = false;
boolean r = a && (b = true); //b가 true로 바뀌지 않음
a = false;
b = false;
r = a & (b = true); //b가 true로 바뀜
각 비트단위로 연산 수행
1 = true, 0 = false 로 간주하고 계산
정수값을 연산할 수 없는 && || ! 와 달리 정수를 비트로 변환시켜 연산 가능
int a = 0b0110_1100;
int b = 0b0101_0101;
System.out.println(a & b); //각 비트단위로 and연산 수행
a = 0000 0000 0000 0000 0000 0000 0110 1100
b = 0000 0000 0000 0000 0000 0000 0101 0101
--------------------------------------------
0000 0000 0000 0000 0000 0000 0100 0100 = 68
(값 % 2) == 0 => 짝수
(값 & 0x1) == 0 => 짝수
ㄴ 맨 뒤의 비트가 1인지만 확인하면 된다는 것
서로 비트가 다르다 = 값의 맨 마지막 값이 0이다-짝수 = 0&1 = 0 == 0 짝수!
어떤 값에 1을 연산시킨다는 뜻은 맨 끝의 1bit만 추출한단뜻
왜써? >> 비트연산이 그냥 %연산보다 계산속도가 빨라서
x % 2 -> x & 0x1(0b01) – 맨 끝의 1비트만 추출
x % 4 -> x & 0x3(0b11) – 맨 끝의 2비트만 추출
x % 8 -> x & 0x7(ob111) – 맨 끝의 3비트만 추출 - 4 2 1 다 더해도 7이니까
n으로 나눈 나머지를 구하는 것과 같음
//ex05.Exam0350 참고
RGB
01100011 11000001 11101011
& 11111111 11111111 01010101
01100011 11000001 00100001
01100011 11000001 11101011
| 10101010 00000000 00000000
11101011 11000001 11101011
&&, ||, ! 의 피연산자(operand)는 반드시 Boolean, 계산 결과도 boolean
&, |, ^, ~(not) 의 피연산자는 정수, 계산 결과도 정수 // float - 컴파일오류
왼쪽으로 비트를 이동
오른쪽 빈자리는 0으로 채움
왼쪽 경계를 넘어간 비트는 자름
int i = 1;
System.out.println(i << 4);
0000[0000000000000000000000000001]
[00000000000000000000000000010000] = 16
1비트 이동은 곱하기 2 한 것과 같은 효과를 준다.
값을 배수로 증가시킬 때 곱하기 연산을 하는 것 보다
왼쪽 비트 이동 연산을 하는 것이 빠르기 때문에
실무에서는 이 비트 이동 연산을 자주 사용한다.
비트 이동 => '2**이동비트'를 곱한 것과 같은 결과를 만든다.
음수의 경우에는 음수부호비트도 같이 왼쪽으로 옮겨지므로 부호가 바뀜
음수를 왼쪽으로 이동시키는 것은 양수를 이동시키는 것과 같은 값
System.out.println(3 << 33); // 6
System.out.println(3 << 65); // 6
System.out.println(3 << 97); // 6
값 3 에 대해 33비트, 65비트, 97 비트를 이동하나 같은 값이 나오는 이유?
-> 4byte = 32bit 값이기때문에
만약 31을 넘는 경우 32로 나눈 나머지 값을 비트 이동으로 간주
-> 8byte = 64bit 값이기때문에
만약 63을 넘는 경우 64로 나눈 나머지 값을 비트 이동으로 간주
// ex05.Exam0412.java 참고
int값은 4byte = 32bit 최대 32비트까지만 이동 가능한 것
그 이상의 값으로 이동시키면? -> 값을 32로 나눈 나머지만큼 이동하는 것
int 값 x << y = x << y`(=y & 0x1F = y % 32)
x << 1 = x << 33 (33%32=1) = x << 65 (65%32=1)
어짜피 큰 수를 줘도 최대 비트 범위 내에서만 이동하므로 범위내의 값을 주는게 나음
왼쪽 쪽 빈자리를 원래 숫자와 같은 부호 값으로 채운다.
양수라면 0, 음수라면 1을 채운다.
오른쪽 경계를 넘어간 비트는 자른다.
int i = 105;
System.out.println(i >> 4);
[00000000000000000000000001101001]
[ 0000000000000000000000000110]1001 => 6
1비트 이동은 나누기 2 한 것과 같은 효과 (나누기 2하고 나머지 제거)
ex. n에 대해 x비트를 오른쪽으로 이동 = n / 2**x
소수점이 있는 경우 그 수 보다 작은 바로 밑 정수 값이 된다.
나누기 연산을 수행하는 것 보다 계산 속도가 빠르다.
실무에서는 나눗셈 연산이 비용(시간과 CPU 사용량)이 많이 들기 때문에
소수점 이하까지 정확하게 계산할 게 아니라면 오른쪽 비트 이동 연산자를 사용하여 주로 처리
오른쪽으로 비트를 이동, 왼쪽 빈자리를 음수 양수 상관없이 무조건 0으로 채움
오른쪽 경계를 넘어간 비트는 자름
Yes/No 또는 true/false 값을 저장할 때 사용하면 메모리 절약할 수 있음
=> 각각의 상태를 별도의 변수에 저장해야 한다.
=> 8개의 데이터를 저장하기 위해 32바이트가 소요된다.
배열 이용 가능
boolean 배열을 JVM에서 다룰 때 각 boolean에 대해 1바이트 사용
=> 따라서 8개의 데이터를 저장하기 위해 8바이트를 사용
=> 4바이트 변수 한 개만 있으면 최대 32개의 데이터를 저장할 수 있음
Q. 10개 항목에 대해 true/false 값 저장
1) Boolean b1, b2, …, b10;
2) Boolean[] arr = new boolean[10];
3) int state; -> 정수 메모리의 각 비트에 항목의 값(true(1)/false(0)) 저장
=> 4byte 만으로 32개 항목에 대해 값 저장 가능
다양한 데이터를 여러 개의 변수를 사용하지 않고도 true / false 두가지 만으로 표현할 수 있게됨
// ex05.Exam0450.java, ex05.Test01 참고
조건 ? 표현식1 : 표현식2
=> 조건이 참이면 표현식1 실행, 거짓이면 표현식2 실행
int a; -> statement
if( ) { } -> statement
a + 2 -> statement (문장)
ㄴ> 실행결과를 리턴 => Expression (표현식)
Expression 표현식 : 결과를 리턴하는 명령문
Statement 문장 : 명령문
statement 중에서 결과를 리턴하는 statement = expression
전위연산자 pre-fix vs 후위연산자 post-fix
++x -> 전위연산자
변수 x의 값 증가시키고, 현재 위치에 변수값 적용
x++ -> 후위연산자
현재 위치에 변수값 적용하고, 변수 x의 값을 증가
int i = 7;
int j = i++;
//컴파일러가 아래처럼 변환시켜 컴파일
int temp = i;
i = i + 1;
int j = temp;
임시저장소 temp 생성
전위/후위 연산자가 없다면 위와 같이 길게 코드를 작성해야함
컴파일할 때 위의 코드로 변환되어 컴파일되기는 함
왜?
연산자 우선순위에 따라 =할당연산자는 오른쪽의 모든 식이 완료되어야 진행
원래 식대로 진행하게되면 원하는 값이 나오지 않을 수 있다 (i++지만 ++i처럼 될수도)
그래서 컴파일러가 i++ 식을 길게 변환시켜 컴퓨터에 입력해 실행하도록 하는 것
int i = 7;
i = i++;
//->
int temp = i;
i = i + 1;
i = temp;
+= -= *= /= %= &= |= ^= <<= >>= >>>=
a = a + 7; = a += 7;
개발자를 위해 만든 단축 문법
실제 컴파일 시 컴파일러는 a+=7 문장을 a=a+7 문장으로 변환 후 컴파일
-> 연산자의 동작을 억지로 이해하려 하지말 것
-> 실제 어떤 문장으로 변환되는지를 아는 것이 문법 이해에 더 도움됨