컴퓨터는 0과 1로 이루어진 이진 코드로 이루어진 기계어를 사용한다. 따라서 컴퓨터와 사람이 소통하기 위해서는 사람의 언어와 기계어의 다리 역할을 하는 프로그래밍 언어가 필요하다.
번역기는 프로그래밍 언어를 실행가능한 기계어로 변환해주는 프로그램을 뜻한다.
① 소스코드를 작성하면 파일명.java로 저장
② javac 파일명.java로 컴파일
③ 파일명.class라는 바이트 코드 파일 생성
④ java 파일명.java로 자바 가상 머신이 바이트 코드 파일 실행
자바는 소스 파일 및 컴파일된 바이트코드 파일을 쉽게 관리하기 위해 패키지를 사용한다. 패키지는 파일 시스템에서의 디렉토리와 비슷하다.
컴퓨터 메모리(RAM)는 수많은 번지들로 구성된 데이터 저장 공간이다. 프로그램은 데이터를 메모리에 저장하고 읽는 작업을 빈번히 수행한다. 이때 데이터를 어디에, 어떻게 저장할지 정해져 있지 않다면 메모리 관리가 무척 어려워진다. 프로그래밍 언어는 변수를 사용해 이 문제를 해결한다.
변수는 하나의 값을 저장할 수 있는 메모리 번지에 붙여진 이름이다. 변수를 통해 프로그램은 메모리 번지에 값을 저장하고 읽을 수 있다.
변수를 사용하기 위해서 자바는 먼저 변수를 선언해야한다. 변수 선언은 어떤 타입의 데이터를 저장할 것인지 그리고 변수 이름이 무엇인지를 선언한다.
변수 선언은 저장되는 값의 타입과 이름만 결정한다. 선언만 이루어진 상태에서는 아직 메모리에 할당이 이루어진 것은 아니다.
변수가 선언되면 대입연산자 =를 활용 하여 해당 변수에 값을 대입할 수 있다. 그리고 변수에 값이 최초로 대입될 때 메모리에 값이 저장된다.
변수에 최초로 값을 대입하는 행위를 변수 초기화라고 한다.
변수는 선언될 때 타입에 따라 저장할 수 있는 값의 종류와 허용 범위가 달라진다. 자바는 정수, 실수, 논리값을 저장할 수 있는 기본 타입 8개를 다음과 같이 제공한다.
타입 | 메모리 크기 | 저장되는 값의 허용 범위 |
---|---|---|
boolean | 1byte(8bit) | ture, false |
char | 2byte(16bit) | 유니코드 문자 |
byte | 1byte(8bit) | -128 ~ 127 |
short | 2byte(16bit) | -32,768 ~ 32,767 |
int | 4byte(32bit) | -2,147,483,648 ~ 2,147,483,647 |
long | 8byte(64bit) | -2^63 ~ (2^63-1) |
float | 4byte(32bit) | 유효 소수 이하자리 7자리 |
double | 8byte(64bit) | 유효 소수 이하자리 15자리 |
코드에서 프로그래머가 직접 입력한 값이다.
변수에 대입할 정수 리터럴은 진수에 따라 작성법이 다르다. 아래는 13을 다르게 표현한 것이다.
int bin = **0b**1101; // 2진수 int oct = **0**15; // 8진수 int deci = 13; // 10진수 int hex = **0x**D; // 16진수
컴파일러는 int로 간주하기 때문에 l을 붙여서 long type 임을 컴파일러에게 알려줘야 한다.
long var1 = 1000000000000; // 컴파일 오류 long var2 = 1000000000000**l**; // Long 타입 인식
하나의 문자를 작은따옴표(')로 감싼 것을 문자 리터럴이라고 한다. 문자 리터럴은 유니코드로 변환되어 저장되는데, 유니코드는 세계 각국의 문자를 0~65535 숫자로 매핑한 국제 표준 규약이다.
char var1 = 'A'; // 유니코드 65로 대입 char var2 = '가'; // 유니코드 44032로 대입
유니코드도 정수이므로 char 타입도 정수 타입에 속한다. 따라서 char 변수에 작은 따옴표로 감싼 문자가 아니라 유니코드 숫자를 직접 대입할 수도 있다.
char var3 = 65; //문자 'A' char var4 = **0x**0041 // 문자 'A'
자바는 ''; 빈 문자를 대입하면 컴파일 에러가 발생한다.
실수 타입에는 float과 double이 있다. 그리고 '정밀도(precision)'라는 개념이 존재한다. 정밀도는 소수점 이하 숫자의 자리수를 의미한다. float의 정밀도는 6~7자리 정도이고, double의 정밀도는 15자리 정도이다. 그러나 정밀도는 상황에 따라서 떨어질 수 있다.
자바는 IEEE 754 표준에 근거해서 float타입과 double타입의 값을 부동 소수점 방식으로 메모리에 저장한다.
부동 소수점 표현은 실수를 정확하게 표현하기 위해 가수와 지수를 이용하여 값을 근사적으로 표현한다.
가수는 소수점 앞 또는 뒤에 있는 유효숫자를 의미한다. 예를 들어, 123.45라는 수를 부동소수점 형식으로 표현하면 1.2345 x 10^2와 같이 표현할 수 있고 이때 12345가 가수에 해당한다.
지수는 10의 몇제곱인지를 나타내는 숫자로, 가수에서 소수점의 위치를 조절하는 역할을 한다. 지수는 양수일 수도 있고, 음수일 수도 있다. 음수일 경우 소수점을 앞으로 이동시키고 양수일 경우 소수점을 뒤로 이동시킨다. 이를 지수 표기법으로 나타내면 1.2345e+2 이다.
부호는 음수인지 양수인지 결정하는 것으로 최상위 1bit가 결정한다.
실수 타입도 정수 타입의 long와 비슷한 경우가 있다. 컴파일러는 기본적으로 double로 인식하기 때문에 float 인 경우 'f'로 컴파이러에게 알려줘야 한다.
float f1 = 3.14; // 컴파일러가 double로 인식 float f2 = 3.14**f**; // 컴파일러가 float으로 인식
참과 거짓을 의미하는 논리 리터럴은 true와 false이다. 논리 리터럴은 boolean 타입 변수에 다음과 같이 대입할 수 있다. 연산식 중에서 비교 및 논리 연산의 산출값은 true 또는 false이므로 boolean 타입 변수에 다음과 같이 대입할 수 있다.
작은따옴표(')로 감싼 한 개의 문자는 char타입이지만, 큰따옴표(")로 감싼 한 개의 문자나 작은따옴표(')로 감싼 여러 개의 문자들은 유니코드로 변환되지 않는다.
char var1 = "A"; // 컴파일 에러 char var2 = 'abc'; // 컴파일 에러 char var1 = 'A';
문자들의 모임을 문자열이라 하고 문자열은 큰따옴표(")로 감싼다. 문자열을 변수에 저장하고 싶다면 String타입을 사용해야 한다.
String은 자바 기본 타입에 속하지 않는 '참조 타입'이다.
자동 타입 변환은 말 그대로 자동으로 타입 변환이 일어나는 것을 말한다. 자동 타입 변환은 값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 대입될 때 발생한다.
기본 타입을 허용 범위 순
정수 타입이 실수 타입으로 대입되는 경우 무조건 자동 타입 변환된다.
long longValue = 5000000000L; float floatValue = longValue; // 5.0e9f로 저장됨 double doubleValue = longValue; // 5.0e9로 저장됨
char 타입의 경우 int 타입으로 자동 변환되면 유니코드 값이 int타입에 대입된다.
char charValue = 'A'; int intValue = charValue; // 65가 저장됨
큰 허용 범위 타입은 작은 허용 범위 타입으로 자동 타입 변환될 수 없다. 마치 큰 그릇을 작은 그릇 안에 넣을 수 없는 것과 같은 이치이다. 하지만 큰 그릇을 작은 그릇 단위로 쪼개서 한 조각만 작은 그릇에 넣는 것은 가능하다.
int intValue = 10 byte byteValue = (byte) intValue; // 캐스팅으로 강제 변환
long longValue = 300; int intValue = (int) longValue; // 강제타입 변환후 300 그대로 유지
int int Value = 65; char charValue = (char) intValue; // 'A'
double doubleValue = 3.14; int intValue = (int) doubleValue; // 정수 부분인 3만 저장
참조 타입인 문자열을 기본 타입으로 바꾸기 위해서는 parse를 사용해야한다.
바꿀기본타입 변수명 = 바꿀기본타입.parse바꿀기본타입(문자열)과 같은 형태로 사용한다.
다만, 기본타입을 문자열로 바꾸려면 String.valueOf(기본타입)과 같은 형태로 사용한다.
String str = "10"; byte value = Byte.parseByte(str);
String str = "200"; short value = Short.parseShort(str);
String str = "300000"; int value = Integer.parseInt(str);
String str = "40000000000"; long value = Long.parseLong(str);
String str = "12.345"; float value = Float.parseFloat(str);
String str = "12.345"; double value = Double.parseDouble(str);
String str = "true"; boolean value = Boolean.parseBoolean(str);
String str = String.valueOf(기본 타입 값);
메소드 블록에는 다른 중괄호 {}블록들이 작성될 수 있다. 이러한 중괄호 {}블록 내에서 선언된 변수는 해당 중괄호 {}블럭 내에서만 사용이 가능하고 밖에서는 사용할 수 없다.
만약 메소드 블록 전체에서 사용하고 싶다면 메소드 블록 첫머리에 선언하는 것이 좋고, 특정 블록 내부에서만 사용된다면 해당 블록 내에서 선언하는 것이 좋다.
System.out.print(); // 출력 System.out.println(); // 출력하고 개행 System.out.printf("형식문자열", 값1 ..); //포맷 스트링
형식 | 설명 | 출력형태 | |
---|---|---|---|
정수 | %d | 정수 | 123 |
%6d | 6자리정수.왼쪽 빈자리 공백 | ___123 | |
%-6d | 6자리정수.오른쪽 빈자리 공백 | 123___ | |
%06d | 6자리 정수.왼쪽 빈자리0채움 | 000123 | |
실수 | %10.2f | 정수 7자리+소수점+소수2자리.왼쪽 빈자리 공백 | ____123.45 |
%-10.2f | 정수 7자리+소수점+소수2자리.오른쪽 빈자리 공백 | 123.45____ | |
%010.2f | 정수 7자리+소수점+소수2자리.왼쪽 빈자리 0채움 | 0000123.45 | |
문자열 | %s | 문자열 | abc |
%6s | 6자리 문자열.왼쪽 빈자리 공백 | ___abc | |
%-6s | 6자리 문자열. 오른쪽 빈자리 공백 | abc___ | |
특수문자 | \t | 탭(tab) | |
\n | 개행 | ||
%% | % | % |
String name = "홍길동"; String job = "도적"; System.out.printf("%s는 %s이다.\n", name, job); System.out.printf("반지름이 %d인 원의 넓이:%10.2\n",10,3.14159*10^2);
키보드로부터 입력된 데이터를 읽고 변수에 저장하는 가장 쉬운 방법은 Scanner를 사용하는 것이다. Scanner 타입 변수를 선언하고, 대입연산자 =를 사용해서 new 연산자로 생성한 Scanner 객체를 변수에 대입한다.
nextLine()은 Enter키가 입력되기 전까지 블로킹(대기) 상태가 되며, Enter키가 입력되면 지금까지 입력된 모든 내용을 문자열로 읽는다.
Scanner scanner = new Scanner(System.in); Scanner inputData = scanner.nextLine();
부호 연산자는 변수의 부호를 변경할 때 사용된다.
주의! 정수타입(byte, short, int)의 연산 결과는 int이다.
증감연산자는 ++로 1씩 증가시키거나 --로 1씩 감소시킨다.
++피연산자는 피연산자의 값을 바로 1씩 증가시킨다.
피연산자++는 다른 연산을 수행한 후에 피연산자의 값을 1씩 증가시킨다.
--또한 감소하는 것을 제외하고는 같다.
boolean result1 = srt1.equals(srt2); // 문자열이 같은지 검사 boolean result2 = !srt1.equals(srt2); // 문자열이 다른지 검사
비트를 좌측 또는 우측으로 밀어서 이동시키는 연산자
우측 피연산자의 값을 좌측 피연산자의 변수에 저장
1순위 : 증감 연산자
2순위 : 산술 연산자
3순위 : 시프트 연산자
4순위 : 비교 연산자
5순위 : 비트 연산자(~만 1순위)
6순위 : 논리 연산자(!만 1순위)
7순위 : 조건(삼항) 연산자
8순위 : 대입 연산자
자바 프로그램은 main()메소드의 시작 중괄호에서 끝 중괄호 까지 위에서 아래로 실행하는 흐름을 가지고 있다. 이러한 실행 흐름을 개발자가 원하는 방향으로 바꿀 수 있도록 해주는 것이 제어문이다. (제어문을 사용할 경우 다양한 실행 흐름이 생성된다.)
조건식의 결과에 따라 블록 실해영부가 결정된다.
// if 문 if (조건식) { 실행문 } // else-if 문 if (조건식) { 실행문 } else if (조건식2) { 실행문2 } else if (조건식3) { 실행문3 } else { 실행문4 }
if문은 true/false 두 가지만의 결과만으로 흐름을 만들어 경우의 수가 많이질 경우 복잡해 질 수 있다. 그러나 switch문은 다양한 결과로 흐름을 만들어 코드가 간결해질 수 있다.
switch(변수) { case 값1 : 실행문1 // 변수가 값1일 때 실행 break; // 브레이크 없으면 밑으로 쭉내려감 case 값2 : 실행문2 // 변수가 값2일 때 실행 break; default: // case에 변수 값과 같은 값이 없으면 실행 }
for (초기화식; 조건식; 증감식) { 실행문 // 조건식이 true일 경우 실행 }
while (조건식) { 실행문 // 조건식이 true일 경우 실행 }
do { 실행문 // 먼저 실행한 번 하고 } while (조건식); // 조건식이 true일 경우 다시 실행
반복문의 실행을 중지하거나 조건문인 switch문을 종료할 때 사용
반복문 블록 내부에서 continue를 만나면 바로 다음 반복여부로 스킵