변수(variable)는 변하는 수로 프로그램 중에 값이 계속 바뀔 수 있는 수인 반면에 상수는 (constant) 한번 할당된 값이 변하지 않는 수를 말한다.
특히 final double PI = 3.141592 처럼 이미 만들어진(정해진) 값이 있어서 누군가 중간에 값을 변경시키면 안되는 것들에 반드시 상수를 사용해야 한다.
(1) 값을 딱 한 번만 할당할 수 있다.
(2) 한 번 할당된 값은 변경이 불가능하다.
(3) 키워드 final 선언이 붙는다.
(1) 상수의 이름은 모두 대문자로 짓는다.
(2) 둘 이상의 단어로 만들 때에는 언더바(_)로 연결한다. (snake 표기법)
변수의 초기화의 의미는 해당 변수에 처음으로 값을 넣는 것이다.
변수의 경우 초기화 이후에 값을 넣어 변화시킬 수 있으나, 상수는 초기화 이후 값을 넣거나 변경시킬 수 없다.
(1) 변수의 초기화
//변수의 선언과 초기화 예시
int a = 1; //변수의 선언과 동시에 초기화
char ch = 'a'; //변수의 선언과 동시에 초기화
int b; //변수의 선언
b = 5; //초기화
(2) 상수의 초기화
final int MAX_SIZE = 100; //상수의 선언과 동시에 초기화
final char CONST_CHAR = '상'; //상수의 선언과 동시에 초기화
final int CONST_ASSIGNED; //상수의 선언
CONST_ASSIGNED = 12; //상수의 초기화
CONST_ASSIGNED = 30; //에러. 상수는 한번만 값을 할당할 수 있다.
리터럴(Literals)은 자료형을 기반으로 표현이 되는 상수를 말한다.
int num = 5 + 7; //5와 7은 '정수형 리터럴'
double num2 = 3.3 + 4.5; //- 3.3 4.5는 '실수형 리터럴'
char ch = 'A' //A는 '문자형 리터럴'
위에서 5나 7, 3.3, 4.5 모두 연산을 위해서 CPU로 보내기 위해 메모리에 올리는 과정이 동반된다. 그렇기 때문에 5와 7은 int형으로 4byte의 메모리 공간을 할당받게 되고 3.3과 4.5는 double형으로 8byte의 메모리 공간을 할당받게 된다. 이렇게 메모리 공간을 확보한 정수와 실수 모두는 메모리 공간에 값이 기록되면 값이 변하지 않기 때문에 리터럴 이라고 표현한다.
(1) 정수형 리터럴
//long형 - L 써야함
long l = 3147483647L;
sysout(3147483647 + 3147483647);
//=> integer number too large 오류메세지 출력
//이진수로 넣으려면 -OB또는 ob붙여서 이진수 표현
byte seven = 0B111; //10진수로 7
int num205 = 0B11001101;
//원하는 위치에 언더바를 넣을 수 있다.
//언더바는 가독성을 위해 넣어주는 것일 뿐, 아무 영향이 없다.
int num = 100_000_000;
int num = 12_34_56_78_90;
(2) 정수형 리터럴
sysout(3.0004999 + 2.0004999);
sysout(3.0004999D + 2.0004999d);
//실수는 기본 double형이다. double임을 명시하기 위해 d또는D삽입 (안넣어도 됨)
sysout(3.0004999F + 2.0004999f);
//실수형 상수를 float형으로 표현하려면 f나 F삽입 (꼭!)
Boolean, 문자형 상수 (예시)
true false: 부울형 상수 (boolean)
'한' '글' 'A' 문자형상수
System.out.println(3147483647 + 3147483648);
정수 리터럴은(3147483647 : 이것도 리터럴) 기본적으로 4byte으로 잡는다.(int형) 여기서는 이미 연산 전의 정수 리터럴이 int의 범위를 넘었다.
System.out.println(3147483647L + 3147483648L);
리터럴 상수에서 숫자 뒤에 L(소문자l도 상관없음)붙이면 long형(8byte)으로 인식해서 long형 상수로 표현해 달라고 요청 하는 것이다.
자료형 변환의 의미와 필요한 이유는 기본적으로 연산 시킬때 두 데이터 타입이 일치해야 하기 때문이다.
int num1 = 50;
long num2 = 3147483647L //<-21억넘음
sysout(num1+num2); //num1에 저장된 값이 long형으로 형 변환된다. (자동형변환)
두 피연산자 자료형이 일치하지 않을 때 형 변환으로 일치 시켜야 한다. 정수와 정수의 연산 에서는 데이터 타입이 큰 쪽으로 맞춘다.(int 보다 작은 데이터 타입은 다 int로 바꾼다.)
강제 형 변환을 하게 될 경우에는 값을 자른다. 자를 때는 앞 부분을 삭제하고 뒤에 있는 바이트가 사용된다.
(1) 의미
자동 형 변환은 자료형의 크기가 일치하지 않지만 강제로 변환하지 않아도 묵시적으로 형 변환이 되는 것을 말한다. 자동 형 변환은 작은 데이터 타입이 큰 쪽으로 변경되거나, 정수형이 실수형으로 변하는 것만 가능하다.
(2) 규칙
자료형 크기가 큰 방향으로 형변환 일어남
자료형 크기에 상관없이 정수 자료형보다 실수 자료형 우선(소수점 보존)
원래의 값을 최대한 보존하는 쪽으로 형변환한다.
(3) 예시
long num1 = 3; //4 byte
float num2 = 22.1f; //8byte
Sytem.out.print(num1+num2);
(1) 의미
자동형변환 규칙에 부합하지 않지만 형변환이 필요한 상황이면 명시적으로 형변환을 진행한다.
이 경우는 데이터가 큰 타입을 작은 타입으로 형 변환을 하는 것도 가능하지만, 실제 데이터의 변형이 일어날 수 있기 때문에 주의해야한다.
(2) 예시
double pi = 3.12415;
int wholeNumber = (int)pi; //정수형 소수점 버리고 결과값은 3
short num1 = 1;
short num2 = 3;
short num3 = (short) (num1 +num2); //num1과 num2 int로 계산될건데 short로 강제 형변
int num4 = (int)num1;
int a = 3;
int b = 4;
double c = a / b;
System.out.println(result);
int 연산 결과는 int인데(소수점 날림) 그 값을 num3으로 대입 하면서 double로 대입해서 .0이 붙게 된다.
(1) 원하는 결괏값인 0.75를 얻기 위해서는 num1, num2의 자료형 중 하나는 double로 선언해야 한다.
int a = 3;
int b = 4;
double result = a/ (double)b
System.out.println(result);
(2) 혹은 연산전에 하나를 double형으로 명시적으로 바꿔주면 제대로된 값을 받을 수 있다.
int a = 3;
double b = 4.0;
double result = a/ b;
System.out.println(num3);
(3) 위에 둘중 하나 자료형만 double로 바꿔되 된다.
(4) 연산시에 숫자가 나온다면 형을 따로 쓰지 않고 3.0 같은 소수점이 있는 수를 사용하면 자동으로 double로 인식해서 계산된다.
이스케이프 시퀀스는 특수 문자로, 백 슬러시 뒤에 문자가 오는 것들을 말한다.
\b 백스페이스 문자 back
\t 탭 tab
\\ 주석처리
\" 작은따옴표문자
\" 큰따옴표문자
\n 개행 line new
\r carrige return :커서를 처음으로 옮겨서 그 자리에 있던 문자를 지우면서 쓰고 개행도 시킴. 결과로 cb나옴 (타자기에서 한번씩 치면 땡기면서 한 칸아래 맨 앞줄로 이동하는 것처럼)
public class Hello {
public static void main(String[] args) {
System.out.println("\'아아\'") ;
}
}
<결과>
'아아'
public class Hello {
public static void main(String[] args) {
System.out.println("AB" + '\b' + 'c');
System.out.println("AB" + '\t' + 'c');
System.out.println("AB" + '\n' + 'c');
System.out.println("AB" + '\r' + 'c');
}
}
결과
이클립스에서 에러. 터미널에서 실행한다.
System.out.println('A'); //char형으로 인식, 메모리에 올라갈 때 65값이 들어감
System.out.println('A' + 'A'); //char형으로 65메모리에 올리고, int형으로 자동
A
130
'A'(리터럴)를 뿌리기 위해 메모리에 방을 잡아야 한다. 이때 데이터 타입이 필요하고 A에 대한 데이터 타입은 char, 메모리에는 아스키코드 값 65가 들어간다.
기본적으로 연산을 할 때는 우선 순위와 결합 방향에 따라 다르게 연산이 이루어진다.
(1) 연산자 우선순위가 높은 것을 먼저 계산한다.
(2) 우선순위가 같다면 결합 방향에 따라 연산된다.
(3) 기본적으로 연산자 우선순위에서 가장 높은 것은 괄호이다.
int a = 6+ 7;
/*
+연산의 우선순위가 =연산의 우선순위보다 높다.
1. +연산을 먼저하고
2. a에 대입한다.
*/
public static void main(String[] args) {
int num1 = 11;
int num2 = 22;
boolean result;
result = (1<num1) && (num1<100);
System.out.println("1초과 100미만인가? : " + result);
}
public static void main(String[] args) {
int num1 = 11;
int num2 = 22;
boolean result;
result = ((num2 % 2) == 0) || ((num2 % 3) == 0);
System.out.println("2 또는 3의 배수인가? : " + result);
}
&&와 ||는 논리 연산자이다.
논리연산자의 리턴값은 boolean으로 항상 true 아니면 false의 결과값을 얻는다.
&& (논리 AND): 모두 true면 true
(예) A && B : A, B모두 true면 결과값은 true
|| (논리 OR): 둘 중 하나만 true면 true
(예) A || B : A, B 둘 중 하나만 true면 결과값은 true
public static void main(String[] args) {
int num1 = 0;
int num2 = 0;
boolean result;
result = ((num1 += 10) < 0) && ((num2 += 10) > 0);
System.out.println("result = " + result);
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2 + '\\n'); // "
result = ((num1 += 10) > 0) || ((num2 += 10) > 0);
System.out.println("result = " + result);
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
}
}
결과
result = ((num += 10 < 0)) && ((num2 += 10) >0);
//둘다 t여야 t이니까 앞에서 이미 false결정되어 뒤에 연산 안함
result = ((num += 10 < 0)) || ((num2 += 10) >0);
//둘중 하나만t면 t니까 앞에서 이미true결정되어 뒤에 연산안함
하지만 연산한 결과는 변수에 반영 된다. 그러므로 다음 연산시에 변한 값이 다시 반영된다.
short num1;
short num = -num;
num은 원래 short이지만 -도 부호연산자로 하나의 연산이고 그래서 int형으로 자동형변환이 일어난다.
즉 -1 * num 의 연산이 일어난다고 볼 수 있으며, int(4byte)형으로 변환된 num을 short(2byte)형 num으로 대입하려 했기 때문에 에러가 난다. (더 작은 타입으로는 자동형변환이 불가능하다.)
short num = 100;
num = (short)(-num);
num++, ++num 은 둘 다 num = num +1 와 같은 의미이다. 하지만 연산의 방법이 다르기 때문에 주의해야한다. 언제 증가와 감소값이 반영되는지 확인 해야하는 것이 중요하다.
전위 연산자 (prefix) : ++n / --n
먼저 1증가 시킨 후 연산에 사용한다.
후위 연산자 (postfix): n++ / n--
값을 먼저 연산에 사용 후 1을 증가시킨다. 하나의 실행 단위가 끝나고 난 뒤 하나 증가 혹은 감소 값을 대입한다.
비트 단위 and 연산(똑같은 것 1로 출력 나머지는 0)
비트 단위 or 연산(둘 중 하나만 1이면 1 나머지는 0)
비트 단위 xor 연산(둘이 서로 다르면 1, 같으면 0)
비트 반전(NOT)(결과값과 반대되는 수 출력)
음수-양수 바뀌면 안되니까, 부호비트는 보존해준다.
0양수 1음수
우측으로 한 칸 비트 이동 (2의n승 혹은 2의 n승분의 1- 값을 2로 나눈 결과) : 제일 뒤 비트 버리고, 남는 앞 비트는 양수면0, 음수면 1을 채운다.
좌측으로 한 칸 비트 이동 (2의n승 만큼 값 변함 - 값 2배 증가) : 제일 앞 비트는 버리고 뒤는 0으로 채운다
public static void main(String[] args) {
int num1 = 10, num2 = 20, num3 = 30;
num1 = num2 = num3;
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
}
}
풀이
연산자는 결합 방향이 오른쪽에서 왼쪽으로 진행된다.
따라서 위의 문장은 다음과 같다.
num1 = (num2 = num3);
(대입 연산자)의 결합 방향은 오른쪽에서 왼쪽 방향으로 이동한다.
그 순서에 따라
(1) 변수 num2 와 num3의 대입 연산의 결과, num2에 num3의 값인 30을 대입한다.
(2) 변수 num1에 num2의 값인 30을 대입한다.
결국, num1, num2, num3에는 모두 같은 값인 30이 들어간다.
결과
30
30
30
public static void main(String[] args) {
int num1 = 0;
int num2 = 0;
boolean result;
num1 += 10;
num2 += 10;
result = (num1 < 0) && (num2 > 0);
System.out.println("result = " + result);
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2 + '\\n'); //+ "\n"??
num1 += 10;
num2 += 10;
result = (num1 > 0) || (num2 > 0);
System.out.println("result = " + result);
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
}
}
풀이
num1 += 10; // num1 = num1 + 10; 과 같아 num1에는 10이 들어감
num2 += 10; // num2 = num2 + 10; 과 같아 num2에도 10이 들어감
result = (num1 < 0) && (num2 > 0);
<, > 연산은 true or false 를 반환한다.
num1(10) < 0 : false , num2(10) > 0 : true
여기서는 <,> 연산의 결과가 결과값에 저장이 안되었다.(변수의 값 변화에 영향 주지 않음)
&&연산은 boolean타입으로 둘다 true여야 true를 반환함: return에 false로 전달
num1 += 10; //num1 = num1 + 10; 과 같아 num1에 20이 들어감
num2 += 10; //num2 = num2 + 10; 과 같아 num2에 20이 들어감
result = (num1 > 0) || (num2 > 0);
위의 result와 유사함
num1(20) > 0 : true , num2(20) > 0 : true
&&연산의 결과 return에 false 전달
결과
result = false
num1 = 10
num2 = 10
result = true
num1 = 20
num2 = 20
public static void main(String[] args) {
int result = 3 + 6;
System.out.println("3 + 6 = " + result);
result += 9;
System.out.println("3 + 6 + 9 = " + result);
result += 12;
System.out.println("3 + 6 + 9 + 12 = " + result);
}
}
해설
int result = 3 + 6;
+연산이 = 연산보다 먼저임
3+6연산의 결과값인 9가 result로 반환됨. result의 현재 값은 9
"3 + 6 = 9" 출력
result += 9;
result = result + 9; 와 같고, result값이 9였으므로 9+9=18이 됨
"3 + 6 + 9 = 18" 출력
result += 12;
result = result + 12; 와 같고, result값이 18이었으므로 18+12=30이 됨
"3 + 6 + 9 +12 = 30" 출력
결과
3 + 6 = 9
3 + 6 + 9 = 18
3 + 6 + 9 +12 = 30
국어 영어 수학 점수를 90 70 80 으로 넣고,
총점과 평균을 구하시오.
public static void main(String[] args) {
int kor = 90;
int eng = 70;
int math = 80;
int sum = kor + eng + math;
System.out.println(sum);
System.out.println(sum / 3.0);
}