0. 요약 및 암기노트
1. Hello World
2. 변수
· 자주 사용하는 타입
- 정수 (int, long) / 실수 (double) / 불린형 (boolean) / 문자열 (String)
· 자바 언어 관례
- 클래스 이름의 첫 글자는 대문자로 시작
- 나머지는 모두 첫 글자를 소문자로 시작
- 여기에 낙타 표기법을 적용
- 예외: 상수는 모두 대문자 사용하고 언더바로 구분
- 예외: 패키지는 모두 소문자 사용
3. 연산자
· 산술 연산자
- + (더하기), - (빼기), * (곱하기), / (나누기), %(나머지)
· 증감 연산자
- ++a (a의 값을 먼저 증가시키고 그 결과를 대입)
- a++ (a의 현재값을 먼저 대입하고 그 후 증가시킴)
· 비교 연산자
- == (동등성), != (불일치), > (크다), < (작다), >= (크거나 같다), <= (작거나 같다)
- 문자열 비교에는 .equals() 메서드 사용
· 논리 연산자
- && (and), || (or), ! (not)
· 대입 연산자
- = (값을 변수에 할당하는 연산자)
4. 조건문
· if문
if (조건) {
} else if (조건) {
} else {
}
· switch문
switch (grade) {
case 1:
coupon = 1000;
break;
case 2:
coupon = 2000;
break;
case 3:
coupon = 3000;
break;
default:
coupon = 500;
· 삼항연산자
String status = (조건) ? 참_표현식 : 거짓_표현식;
5. 반복문
· while문
- 참이면 코드 블럭을 실행하고, 거짓이면 while문을 벗어난다
while (조건식) {
// 코드
}
· do-while문
- 최초 1회는 실행 후 참이면 코드 블럭을 실행하고, 거짓이면 while문을 벗어난다
do {
// 코드
} while (조건);
· break
- 반복문을 즉시 종료하고 나간다.
· continue
- 반복문의 나머지 부분을 건너뛰고 다음 반복으로 진행한다.
· for문
1. 초기식 실행 (딱 1번 사용)
2. 조건식 검증: 참이면 코드를 실행, 거짓이면 for문을 빠져나감
3. 코드 실행
4. 증감식 실행
5. 2. 조건식부터 시작
for (1.초기식; 2.조건식; 4.증감식) {
// 3.코드
}
6. 스코프, 형변환
· 스코프
- 변수의 접근 가능한 범위
· 자동 형변환
- 작은 범위 숫자 타입에서 큰 범위 숫자 타입으로의 대입은 자동적으로 변환된다 (묵시적 형변환)
· 명시적 형변환
- 손실 발생 감수하고 변환시킴
intValue = (int) doubleValue
7. 훈련
· Scanner
- System.in 을 통해서 사용자의 입력 받기
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine(); // 입력을 String으로 가져옵니다.
int intValue = scanner.nextInt(); // 입력을 int로 가져옵니다.
double doubleValue = scanner.nextDouble(); // 입력을 double로 가져옵니다.
8. 배열
// 배열 생성과 초기화
int[] students;
students = new int[]{90, 80, 70, 60, 50};
// 배열 변수 선언, 배열 생성과 초기화 한번에
int[] students = new int[]{90, 80, 70, 60, 50};
// 배열의 편리한 초기화
int[] students = {90, 80, 70, 60, 50};
· 2차원 배열
int[][] arr = new int[2][3]; //행(row), 열(column)
arr[0][0] = 1; //0행, 0열
arr[0][1] = 2; //0행, 1열
arr[0][2] = 3; //0행, 2열
arr[1][0] = 4; //1행, 0열
arr[1][1] = 5; //1행, 1열
arr[1][2] = 6; //1행, 2열
// 2x3 2차원 배열, 초기화
int[][] arr = {
{1, 2, 3},
{4, 5, 6}
};
9. 메서드
· 자바에서는 함수를 메서드라 한다.
public static int add(int a, int b) {
//메서드 본문, 실행 코드
}
제어자 반환타입 메서드이름(매개변수 목록) {
메서드 본문
}
· 메서드 오버로딩
- 자바는 메서드의 이름 뿐만 아니라 매개변수 정보를 함께 사용해서 메서드를 구분한다.
// 오버로딩 성공
add(int a, int b)
add(int a, int b, int c)
add(double a, double b)
// 오버로딩 실패
int add(int a, int b)
double add(int a, int b)
1. Hello World
1.1. 자바 프로그램 실행
public class HelloJava {
public static void main(String[] args) {
System.out.println("hello java");
}
}
▶결과
hello java
주의!!!!
· 자바 언어는 대소문자를 구분한다.
· 대소문자가 다르면 오류가 발생할 수 있다.
1.2. 주석(comment)
public class CommentJava {
public static void main(String[] args) {
System.out.println("hello java1"); // hello java1을 출력합니다. (한 줄 주석 - 부분 적용)
// System.out.println("hello java2"); 한 줄 주석 - 라인 전체 적용
/* 여러 줄 주석
System.out.println("hello java3");
System.out.println("hello java4");
*/
}
}
▶결과
hello java1
1.3. 자바란?
· 변경의 용이

· 컴파일과 실행

· IntelliJ를 통한 자바 컴파일, 실행 과정

· 자바와 운영체제 독립성

· 자바 개발과 운영 환경

2. 변수
2.1. 변수 선언과 초기화
package variable;
public class Var {
public static void main(String[] args) {
// 1. 변수 선언, 초기화 각각 따로
int a; // 변수 선언
a = 10; // 변수 초기화
System.out.println(a); // 10 출력
a = 50; // 변수 값 변경: a(10 -> 50)
System.out.println(a); // 50 출력
int b = 2; // 2. 변수 선언과 초기화를 한번에
int c = 3, d = 4; // 3. 여러 변수 선언과 초기화를 한번에
}
}
· 변수는 초기화해야한다.
- 변수를 선언하면 메모리상의 어떤 공간을 차지하고 사용한다.
- 그런데 그 공간에 기존에 어떤 값이 있었는지는 아무도 모른다.
- 따라서 초기화를 하지 않으면 이상한 값이 출력될 수 있다.
- 이런 문제를 예방하기 위해 자바는 변수를 초기화 하도록 강제한다.
참고!!!!
지금 다루는 변수는 지역 변수(Local Variable)라고 하는데, 지역 변수는 개발자가 직접 초기화를 해주어야 한다.
나중에 나올 클래스 변수와 인스턴스 변수는 자바가 자동으로 초기화를 진행해준다.
참고!!!!
컴파일 에러는 자바 문법에 맞지 않았을 때 발생하는 에러이다.
컴파일 에러는 오류를 빨리, 그리고 명확하게 찾을 수 있기 때문에 사실은 좋은 에러이다.
덕분에 빠르게 버그를 찾아서 고칠 수 있다.
2.2. 변수 타입
public class Var {
public static void main(String[] args) {
int a = 100; // 정수
double b = 10.5; // 실수
boolean c = true; // 불리언(boolean) true, false 입력 가능
char d = 'A'; // 문자 하나
String e = "Hello Java"; // 문자열, 문자열을 다루기 위한 특별한 타입
}
}
· 변수 타입의 예
· int : 정수를 다룬다.
- 예) 1 , 100 , 1000
· double : 실수를 다룬다.
- 예) 0.2 , 1.5 , 100.121
· boolean : 불리언 타입. true , false 값만 사용 가능.
· char : 문자 하나를 다룰 때 사용한다. 작은따옴표( ' )를 사용해서 감싸야 한다.
- 예) 'A' , '가'
· String : 문자열을 다룬다. 큰따옴표( " )를 사용해야 한다.
- 예) "hello java"
· 자신의 타입에 맞는 데이터를 사용해야 한다.
· 리터럴
- 코드에서 개발자가 직접 적은 100 , 10.5 , true , 'A' , "Hello Java" 와 같은 고정된 값을 프로그래밍 용어로 리터럴(literal)이라 한다.
int a = 100; // 정수 리터럴
double b = 10.5; // 실수 리터럴
boolean c = true; // 불리언 리터럴
char d = 'A'; // 문자 하나 리터럴
String e = "Hello Java"; // 문자열 리터럴
· 변수와 메모리 공간 크기
· 정수형
- byte : -128 ~ 127 (1byte, 2⁸)
- short : -32,768 ~ 32,767 (2byte, 2¹⁶)
- int : -2,147,483,648 ~ 2,147,483,647 (약 20억) (4byte, 2³²)
- long : -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 (8byte, 2⁶⁴)
· 실수형
- float : 대략 -3.4E38 ~ 3.4E38, 7자리 정밀도 (4byte, 2³²)
- double : 대략 -1.7E308 ~ 1.7E308, 15자리 정밀도 (8byte, 2⁶⁴)
· 기타
- boolean : true , false (1byte)
- char : 문자 하나(2byte)
- String : 문자열을 표현한다. 메모리 사용량은 문자 길이에 따라 동적으로 달라진다. (특별한 타입)
· 리터럴 타입 지정
· 정수 리터럴은 int 를 기본으로 사용한다.
· 따라서 int 범위까지 표현할 수 있다.
· 숫자가 int 범위인 약 20억을 넘어가면 L 을 붙여서 정수 리터럴을 long 으로 변경해야 한다.
(대문자 L , 소문자 l 모두 가능하다 그런데 소문자 l 은 숫자 1과 착각할 수 있어서 권장하지 않는다.)
· 실수 리터럴은 기본이 double 형을 사용한다. float 형을 사용하려면 f 를 붙여서 float 형으로 지정해야 한다.
2.3. 변수 타입 정리
· 다음 타입은 실무에서 거의 사용하지 않는다
· byte : 표현 길이가 너무 작다. 또 자바는 기본으로 4byte( int )를 효율적으로 계산하도록 설계되어 있다. int 를 사용하자.
- byte 타입을 직접 선언하고 여기에 숫자 값을 대입해서 계산하는 일은 거의 없다.
- 대신에 파일을 바이트 단위로 다루기 때문에 파일 전송, 파일 복사 등에 주로 사용된다.
· short : 표현 길이가 너무 작다. 또 자바는 기본으로 4byte( int )를 효율적으로 계산하도록 설계되어 있다. int 를 사용하자
· float : 표현 길이와 정밀도가 낮다. 실수형은 double 을 사용하자.
· char : 문자 하나를 표현하는 일은 거의 없다. 문자 하나를 표현할 때도 문자열을 사용할 수 있다.
- 예를 들어 String a = "b" 와 같이 사용하면 된다.
· 자주 사용하는 타입
· 정수 - int, long
- 자바는 정수에 기본으로 int를 사용한다.
- 만약 20억이 넘을 것 같으면 long을 쓰면 된다.
- 파일을 다룰 때는 byte를 사용한다.
· 실수 - double
- 실수는 고민하지 말고 double을 쓰면 된다.
· 불린형 - boolean
- true, false 참 거짓을 표현한다. 이후 조건문에서 자주 사용된다.
· 문자열 - String
- 문자를 다룰 때는 문자 하나든 문자열이든 모두 String을 사용하는 것이 편리하다.
2.4. 변수 명명 규칙
· 변수 이름은 숫자로 시작할 수 없다. (예: 1num , 1st )
- 그러나 숫자를 이름에 포함하는 것은 가능하다 (예: myVar1 , num1 ).
· 이름에는 공백이 들어갈 수 없다.
· 자바의 예약어를 변수 이름으로 사용할 수 없다. (예: int , class , public )
· 변수 이름에는 영문자( a-z , A-Z ), 숫자( 0-9 ), 달러 기호( $ ) 또는 밑줄( _ )만 사용할 수 있다.
2.5. 자바 언어의 관례 한번에 정리
· 자바에서 클래스 이름의 첫 글자는 대문자로 시작한다.
· 그리고 나머지는 모두 첫 글자를 소문자로 시작한다.
· 여기에 낙타 표기법을 적용하면 된다.
· 이렇게 하면 모든 자바 관례를 다 외울 수 있다!
· 예시: 클래스는 첫 글자 대문자, 나머지는 모두 첫 글자 소문자로 시작 + 낙타 표기법
- 클래스: Person , OrderDetail
- 변수를 포함한 나머지: firstName , userAccount
· 여기에 예외가 딱 2개 있다.
- 상수는 모두 대문자를 사용하고 언더바로 구분한다. USER_LIMIT
- 패키지는 모두 소문자를 사용한다. org.spring.boot
3. 연산자
3.1. 산술 연산자
· + (더하기)
· - (빼기)
· * (곱하기)
· / (나누기)
· % (나머지)
public class Operator1 {
public static void main(String[] args) {
int a = 5, b = 2; // 변수 초기화
int sum = a + b; // 덧셈
System.out.println("a + b = " + sum); // 출력: a + b = 7
int diff = a - b; // 뺄셈
System.out.println("a - b = " + diff); // 출력: a - b = 3
int multi = a * b; // 곱셈
System.out.println("a * b = " + multi); // 출력: a * b = 10
int div = a / b; // 나눗셈
System.out.println("a / b = " + div); // 출력: a / b = 2
int mod = a % b; // 나머지
System.out.println("a % b = " + mod); // 출력: a % b = 1
}
}
3.2. 문자열 더하기
public class Operator {
public static void main(String[] args) {
// 문자열과 문자열 더하기1
String result1 = "hello " + "world";
System.out.println(result1);
// 문자열과 문자열 더하기2
String s1 = "string1";
String s2 = "string2";
String result2 = s1 + s2;
System.out.println(result2);
// 문자열과 숫자 더하기1
String result3 = "a + b = " + 10;
System.out.println(result3);
// 문자열과 숫자 더하기2
int num = 20;
String str = "a + b = ";
String result4 = str + num;
System.out.println(result4);
}
}
▶결과
hello world
string1string2
a + b = 10
a + b = 20
3.3. 연산자 우선순위
※ 외울 필요 없다. 개발에서 가장 중요한 것은 단순함과 명확함이다! 애매하거나 복잡하면 안된다.
1. 상식선에서 우선순위를 사용하자
2. 애매하면 괄호를 사용하자
3.4. 증감 연산자
· ++a : 증감 연산자를 피연산자 앞에 둘 수 있다. 이것을 앞에 있다고 해서 전위(Prefix) 증감 연산자라 한다.
· a++ : 증감 연산자를 피연산자 뒤에 둘 수 있다. 이것을 뒤에 있다고 해서 후위(Postfix) 증감 연산자라 한다
public class Operator{
public static void main(String[] args) {
// 전위 증감 연산자 사용 예
int a = 1;
int b = 0;
b = ++a; // a의 값을 먼저 증가시키고, 그 결과를 b에 대입
System.out.println("a = " + a + ", b = " + b); // 결과: a = 2, b = 2
// 후위 증감 연산자 사용 예
a = 1; // a 값을 다시 1로 지정
b = 0; // b 값을 다시 0으로 지정
b = a++; // a의 현재 값을 b에 먼저 대입하고, 그 후 a 값을 증가시킴
System.out.println("a = " + a + ", b = " + b); // 결과: a = 2, b = 1
}
}
▶결과
a = 2, b = 2
a = 2, b = 1


3.5. 비교 연산자
· == : 동등성 (equal to)
· != : 불일치 (not equal to)
· > : 크다 (greater than)
· < : 작다 (less than)
· >= : 크거나 같다 (greater than or equal to)
· <= : 작거나 같다 (less than or equal to)
· 문자열 비교
- 문자열이 같은지 비교할 때는 == 이 아니라 .equals() 메서드를 사용해야 한다.
public class Comp {
public static void main(String[] args) {
String str1 = "문자열1";
String str2 = "문자열2";
boolean result1 = "hello".equals("hello"); // 리터럴 비교
boolean result2 = str1.equals("문자열1"); // 문자열 변수, 리터럴 비교
boolean result3 = str1.equals(str2); // 문자열 변수 비교
System.out.println("result1 = " + result1);
System.out.println("result2 = " + result2);
System.out.println("result3 = " + result3);
}
}
▶결과
result1 = true
result2 = true
result3 = false
3.6. 논리 연산자
· && (and, 그리고) : 두 피연산자가 모두 참이면 참을 반환, 둘중 하나라도 거짓이면 거짓을 반환
· || (or, 또는) : 두 피연산자 중 하나라도 참이면 참을 반환, 둘다 거짓이면 거짓을 반환
· ! (not, 부정) : 피연산자의 논리적 부정을 반환. 즉, 참이면 거짓을, 거짓이면 참을 반환
public class Logical {
public static void main(String[] args) {
int a = 15;
// a는 10보다 크고 20보다 작다
boolean result = a > 10 && a < 20; // (a > 10) && (a < 20)
System.out.println("result = " + result);
}
}
▶결과
result = true
3.7. 대입 연산자
· 대입 연산자( = )는 값을 변수에 할당하는 연산자다. 이 연산자를 사용하면 변수에 값을 할당할 수 있다.
· 축약(복합) 대입 연산자
public class Assign {
public static void main(String[] args) {
int a = 5; // 5
a += 3; // 8 (5 + 3): a = a + 3
a -= 2; // 6 (8 - 2): a = a - 2
a *= 4; // 24 (6 * 4): a = a * 4
a /= 3; // 8 (24 / 3): a = a / 3
a %= 5; // 3 (8 % 5) : a = a % 5
System.out.println(a);
}
}
▶결과
3
4. 조건문
4.1. if문
· if 문을 각각 사용할지, if 와 else if 를 함께 묶어서 사용할지는 요구사항에 따라 다르다.
public class If {
public static void main(String[] args) {
int price = 10000; // 아이템 가격
int age = 10; // 나이
int discount = 0;
if (price >= 10000) {
discount = discount + 1000;
System.out.println("10000원 이상 구매, 1000원 할인");
} else if (age <= 10) {
discount = discount + 1000;
System.out.println("어린이 1000원 할인");
} else {
System.out.println("할인 없음");
}
System.out.println("총 할인 금액: " + discount + "원");
}
}
· if문 {} 중괄호 생략
- 다음과 같이 if 문 다음에 실행할 명령이 하나만 있을 경우에는 {} 중괄호를 생략할 수 있다.
- else if , else 도 마찬가지이다.
if (true) System.out.println("if문에서 실행됨");
4.2. switch문
public class Switch {
public static void main(String[] args) {
// grade 1:1000, 2:2000, 3:3000, 나머지: 500
int grade = 2;
int coupon;
switch (grade) {
case 1:
coupon = 1000;
break;
case 2:
coupon = 2000;
break;
case 3:
coupon = 3000;
break;
default:
coupon = 500;
}
System.out.println("발급받은 쿠폰 " + coupon);
}
}
▶결과
발급받은 쿠폰 2000
· 조건식의 결과 값이 어떤 case 의 값과 일치하면 해당 case 의 코드를 실행한다.
· break 문은 현재 실행 중인 코드를 끝내고 switch 문을 빠져나가게 하는 역할을 한다.
· 만약 break 문이 없으면, 일치하는 case 이후의 모든 case 코드들이 순서대로 실행된다.
· default 는 조건식의 결과값이 모든 case 의 값과 일치하지 않을 때 실행된다. if 문의 else 와 같다.
· default 구문은 선택이다.
· if , else-if , else 구조와 동일하다.
· 정리하자면 swtich 문 없이 if 문만 사용해도 된다. 하지만 특정 값에 따라 코드를 실행할 때는 switch 문을 사용하면 if 문 보다 간결한 코드를 작성할 수 있다.
· 자바 14 새로운 switch문
public class Switch {
public static void main(String[] args) {
// grade 1:1000, 2:2000, 3:3000, 나머지: 500
int grade = 2;
int coupon = switch (grade) {
case 1 -> 1000;
case 2 -> 2000;
case 3 -> 3000;
default -> 500;
};
System.out.println("발급받은 쿠폰 " + coupon);
}
}
· -> 를 사용한다.
· 선택된 데이터를 반환할 수 있다.
4.3. 삼항 연산자
· 단순히 참과 거짓에 따라서 특정 값을 구하는 경우 삼항 연산자 또는 조건 연산자라고 불리는 ?: 연산자를 사용할 수 있다. 이 연산자를 사용하면 if 문과 비교해서 코드를 단순화 할 수 있다.
· (조건) ? 참_표현식 : 거짓_표현식
public class CondOp {
public static void main(String[] args) {
int age = 18;
String status = (age >= 18) ? "성인" : "미성년자";
System.out.println("age = " + age + " status = " + status);
}
}
· 실행결과 분석
String status = (age >= 18) ? "성인" : "미성년자"; // age=18
String status = (true) ? "성인" : "미성년자"; // 조건이 참이므로 참 표현식 부분이 선택된다.
String status = "성인"; // 결과
5. 반복문
5.1. while문
· while문은 조건에 따라 코드를 반복해서 실행할 때 사용한다.
· 구조
while (조건식) {
// 코드
}
· 조건식을 확인한다. 참이면 코드 블럭을 실행하고, 거짓이면 while문을 벗어난다.
· 조건식이 참이면 코드 블럭을 실행한다. 이후에 코드 블럭이 끝나면 다시 조건식 검사로 돌아가서 조건식을 검사한다.(무한 반복)
public class While {
public static void main(String[] args) {
int count = 0;
while (count < 3) {
count++;
System.out.println("현재 숫자는:" + count);
}
}
}
5.2. do-while문
· do-while 문은 while 문과 비슷하지만, 조건에 상관없이 무조건 한 번은 코드를 실행한다.
· 구조
do {
// 코드
} while (조건식);
public class DoWhile {
public static void main(String[] args) {
int i = 10;
do {
System.out.println("현재 숫자는:" + i);
i++;
} while (i < 3);
}
}
5.3. break, continue
· break 와 continue 는 반복문에서 사용할 수 있는 키워드다.
· break 는 반복문을 즉시 종료하고 나간다.
· continue 는 반복문의 나머지 부분을 건너뛰고 다음 반복으로 진행하는 데 사용된다.
· 참고로 while, do-while, for와 같은 모든 반복문에서 사용할 수 있다.
· break
while (조건식) {
코드1;
break; // 즉시 while문 종료로 이동한다.
코드2;
}
//while문 종료
· continue
while (조건식) {
코드1;
continue; // 즉시 조건식으로 이동한다.
코드2;
}
5.4. for문
· for문도 while문과 같은 반복문이고, 코드를 반복 실행하는 역할을 한다.
· for문은 주로 반복 횟수가 정해져 있을 때 사용한다.
· 구조
for (1.초기식; 2.조건식; 4.증감식) {
// 3.코드
}
1. 초기식이 실행된다. 주로 반복 횟수와 관련된 변수를 선언하고 초기화 할 때 사용한다. 초기식은 딱 1번 사용된다.
2. 조건식을 검증한다. 참이면 코드를 실행하고, 거짓이면 for문을 빠져나간다.
3. 코드를 실행한다.
4. 코드가 종료되면 증감식을 실행한다. 주로 초기식에 넣은 반복 횟수와 관련된 변수의 값을 증가할 때 사용한다.
5. 다시 2. 조건식 부터 시작한다. (무한 반복)
· for문은 복잡해 보이지만 while문을 조금 더 편하게 다룰 수 있도록 구조화 한 것 뿐이다.
· for문에서 초기식, 조건식, 증감식은 선택이다. 다음과 같이 모두 생략해도 된다. 단 생략해도 각 영역을 구분하는 세미콜론( ; )은 유지해야 한다.
for ( ; ; ) {
// 코드
}
· 이렇게 하면 조건이 없기 때문에 무한 반복하는 코드가 된다. 따라서 다음과 같은 코드가 된다.
while (true) {
// 코드
}
6. 스코프, 형변환
6.1. 스코프
· 변수는 선언한 위치에 따라 지역 변수, 멤버 변수(클래스 변수, 인스턴스 변수)와 같이 분류된다.
· 지역 변수는 이름 그대로 특정 지역에서만 사용할 수 있는 변수라는 뜻이다. 그 특정 지역을 벗어나면 사용할 수 없다. 여기서 말하는 지역이 바로 변수가 선언된 코드 블록( {} )이다. 지역 변수는 자신이 선언된 코드 블록( {} ) 안에서만 생존하고, 자신이 선언된 코드 블록을 벗어나면 제거된다. 따라서 이후에는 접근할 수 없다.
public class Scope {
public static void main(String[] args) {
int m = 10; // m 생존 시작
if (true) {
int x = 20; // x 생존 시작
System.out.println("if m = " + m); // 블록 내부에서 블록 외부는 접근 가능
System.out.println("if x = " + x);
} // x 생존 종료
// System.out.println("main x = " + x); // 오류, 변수 x에 접근 불가
System.out.println("main m = " + m);
} // m 생존 종료
}
· 이렇게 변수의 접근 가능한 범위를 스코프(Scope)라 한다. 참고로 Scope를 번역하면 범위라는 뜻이다.
· 변수는 꼭 필요한 범위로 한정해서 사용하는 것이 좋다. 변수의 스코프는 꼭 필요한 곳으로 한정해서 사용하자. 메모리를 효율적으로 사용하고 더 유지보수하기 좋은 코드를 만들 수 있다.
· 좋은 프로그램은 무한한 자유가 있는 프로그램이 아니라 적절한 제약이 있는 프로그램이다.
6.2. 자동 형변환
· 작은 범위에서 큰 범위로는 당연히 값을 넣을 수 있다.
예) int → long → double
· 큰 범위에서 작은 범위는 다음과 같은 문제가 발생할 수 있다.
예) 소수점 버림, 오버플로우
· 하지만 결국 대입하는 형(타입)을 맞추어야 하기 때문에 개념적으로는 다음과 같이 동작한다.
//intValue = 10
doubleValue = intValue
doubleValue = (double) intValue // 형 맞추기
doubleValue = (double) 10 // 변수 값 읽기
doubleValue = 10.0 // 형변환
· 이렇게 앞에 (double) 과 같이 적어주면 int 형이 double 형으로 형이 변한다. 이렇게 형이 변경되는 것을 형변환이라 한다.
· 작은 범위 숫자 타입에서 큰 범위 숫자 타입으로의 대입은 개발자가 이렇게 직접 형변환을 하지 않아도 된다. 이런 과정이 자동으로 일어나기 때문에 자동 형변환, 또는 묵시적 형변환이라 한다.
6.3. 명시적 형변환
· 큰 범위에서 작은 범위 대입은 명시적 형변환이 필요하다.
· int 형은 double 형보다 숫자의 표현 범위가 작다. 그리고 실수를 표현할 수도 없다. 따라서 이 경우 숫자가 손실되는 문제가 발생할 수 있다. 쉽게 이야기해서 큰 컵에 담긴 물을 작은 컵에 옮겨 담으려고 하니, 손실이 발생할 수 있다는 것이다.
· 하지만 만약 이런 위험을 개발자가 직접 감수하고도 값을 대입하고 싶다면 데이터 타입을 강제로 변경할 수 있다.
//doubleValue = 1.5
intValue = (int) doubleValue;
intValue = (int) 1.5; // doubleValue에 있는 값을 읽는다.
intValue = 1; // (int)로 형변환 한다. intValue에 int형인 숫자 1을 대입한다.
· 형변환 후 출력해보면 숫자 1 이 출력되는 것을 확인할 수 있다.
· 형변환과 오버플로우
public class Casting {
public static void main(String[] args) {
long maxIntValue = 2147483647; // int 최고값
long maxIntOver = 2147483648L; // int 최고값 + 1(초과)
int intValue = 0;
intValue = (int) maxIntValue; // 형변환
System.out.println("maxIntValue casting=" + intValue); // 출력:2147483647
intValue = (int) maxIntOver; // 형변환
System.out.println("maxIntOver casting=" + intValue); // 출력:-2147483648
}
}
▶결과
maxIntValue casting=2147483647
maxIntOver casting=-2147483648
· 결과를 보면 -2147483648 이라는 전혀 다른 숫자가 보인다. int 형은 2147483648L 를 표현할 수 있는 방법이 없다. 이렇게 기존 범위를 초과해서 표현하게 되면 전혀 다른 숫자가 표현되는데, 이런 현상을 오버플로우라한다.
· 보통 오버플로우가 발생하면 마치 시계가 한바퀴 돈 것 처럼 다시 처음부터 시작한다. 참고로 -2147483648 숫자는 int 의 가장 작은 숫자이다.
6.4. 계산과 형변환
public class Casting4 {
public static void main(String[] args) {
int div1 = 3 / 2;
System.out.println("div1 = " + div1); // 1
double div2 = 3 / 2;
System.out.println("div2 = " + div2); // 1.0
double div3 = 3.0 / 2;
System.out.println("div3 = " + div3); // 1.5
double div4 = (double) 3 / 2;
System.out.println("div4 = " + div4); // 1.5
int a = 3;
int b = 2;
double result = (double) a / b;
System.out.println("result = " + result); // 1.5
}
}
▶결과
div1 = 1
div2 = 1.0
div3 = 1.5
div4 = 1.5
result = 1.5
· 같은 타입끼리의 계산은 같은 타입의 결과를 낸다.
- int + int 는 int 를, double + double 은 double 의 결과가 나온다.
· 서로 다른 타입의 계산은 큰 범위로 자동 형변환이 일어난다.
- int + long 은 long + long 으로 자동 형변환이 일어난다.
- int + double 은 double + double 로 자동 형변환이 일어난다.
7. 훈련
7.1. Scanner
· System.out 을 통해서 출력을 했듯이, System.in 을 통해서 사용자의 입력을 받을 수 있다.
· 그런데 자바가 제공하는 System.in 을 통해서 사용자 입력을 받으려면 여러 과정을 거쳐야해서 복잡하고 어렵다.
· 자바는 이런 문제를 해결하기 위해 Scanner 라는 클래스를 제공한다.
import java.util.Scanner;
public class Scanner1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("문자열을 입력하세요:");
String str = scanner.nextLine(); // 입력을 String으로 가져옵니다.
System.out.println("입력한 문자열: " + str);
System.out.print("정수를 입력하세요:");
int intValue = scanner.nextInt(); // 입력을 int로 가져옵니다.
System.out.println("입력한 정수: " + intValue);
System.out.print("실수를 입력하세요:");
double doubleValue = scanner.nextDouble(); // 입력을 double로 가져옵니다.
System.out.println("입력한 실수: " + doubleValue);
}
}
▶결과
문자열을 입력하세요:hello
입력한 문자열: hello
정수를 입력하세요:10
입력한 정수: 10
실수를 입력하세요:1.5
입력한 실수: 1.5
· Scanner scanner = new Scanner(System.in);
- 이 코드는 객체와 클래스를 배워야 정확히 이해할 수 있다.
- 지금은 Scanner 의 기능을 사용하기 위해 new 를 사용해서 Scanner 를 만든다 정도로 이해하면 된다.
- Scanner 는 System.in 을 사용해서 사용자의 입력을 편리하게 받도록 도와준다.
- Scanner scanner 코드는 scanner 변수를 선언하는 것이다. 이제부터 scanner 변수를 통해서 scanner 를 사용할 수 있다.
· scanner.nextLine()
- 엔터( \n )을 입력할 때 까지 문자를 가져온다.
· scanner.nextInt()
- 입력을 int 형으로 가져온다. 정수 입력에 사용한다.
· scanner.nextDouble()
- 입력을 double 형으로 가져온다. 실수 입력에 사용한다.
8. 배열
8.1. 배열이 필요한 이유
· 같은 타입의 변수를 반복해서 선언하고 반복해서 사용하는 문제를 해결하는 것이 바로 배열이다.
8.2. 배열의 선언과 생성
public class ArrayRef {
public static void main(String[] args) {
int[] students; // 배열 변수 선언
students = new int[5]; // 배열 생성
//변수 값 대입
students[0] = 90;
students[1] = 80;
students[2] = 70;
students[3] = 60;
students[4] = 50;
}
}
1. 배열 변수 선언

· 배열을 사용하려면 int[] students; 와 같이 배열 변수를 선언해야 한다.
· 배열 변수를 선언한다고해서 아직 사용할 수 있는 배열이 만들어진 것은 아니다!
2. 배열 생성

· 배열을 사용하려면 배열을 생성해야 한다.
· new int[5] 라고 입력하면 오른쪽 그림과 같이 총 5개의 int 형 변수가 만들어진다.
· new 는 새로 생성한다는 뜻이고, int[5] 는 int 형 변수 5개라는 뜻이다.
· 따라서 int 형 변수 5개를 다룰 수 있는 배열을 새로 만든다는 뜻이다.
3. 배열과 초기화
· new int[5] 라고 하면 총 5개의 int 형 변수가 만들어진다.
· 자바는 배열을 생성할 때 그 내부값을 자동으로 초기화한다.
· 숫자는 0 , boolean 은 false , String 은 null (없다는 뜻이다.)로 초기화 된다.
4. 배열 참조값 보관

· new int[5] 로 배열을 생성하면 배열의 크기만큼 메모리를 확보한다. (int 형을 5개 사용하면 4byte * 5 20byte 를 확보)
· 배열을 생성하고 나면 자바는 메모리 어딘가에 있는 이 배열에 접근할 수 있는 참조값(주소)( x001 )을 반환한다.
- 여기서 x001 이라고 표현한 것이 참조값이다. (실제로 x001 처럼 표현되는 것은 아니고 이해를 돕기 위한 예시이다.)
· 앞서 선언한 배열 변수인 int[] students 에 생성된 배열의 참조값( x001 )을 보관한다.
· int[] students 변수는 new int[5] 로 생성한 배열의 참조값을 가지고 있다.
- 이 변수는 참조값을 가지고 있다. 이 참조값을 통해 배열을 참조할 수 있다. 쉽게 이야기해서 참조값을 통해 메모리에 있는 실제 배열에 접근하고 사용할 수 있다.
- 참고로 배열을 생성하는 new int[5] 자체에는 아무런 이름이 없다! 그냥 int 형 변수를 5개 연속으로 만드는 것이다. 따라서 생성한 배열에 접근하는 방법이 필요하다. 따라서 배열을 생성할 때 반환되는 참조값을 어딘가에 보관해두어야 한다. 앞서 int[] students 변수에 참조값( x001 )을 보관해두었다. 이 변수를 통해서 이 배열에 접근할 수 있다.
8.3. 배열 사용
· 인덱스
- 배열은 변수와 사용법이 비슷한데, 차이점이 있다면 다음과 같이 [] 사이에 숫자 번호를 넣어주면 된다.
- 배열의 위치를 나타내는 숫자를 인덱스(index)라 한다

· 배열은 0 부터 시작한다.
- new int[5] 와 같이 5개의 요소를 가지는 int 형 배열을 만들었다면 인덱스는 0,1,2,3,4 가 존재한다.
8.4. 배열 리펙토링 - 초기화
· 배열은 {} 를 사용해서 생성과 동시에 편리하게 초기화 하는 기능을 제공한다.
// 배열 생성과 초기화
int[] students;
students = new int[]{90, 80, 70, 60, 50};
// 배열 변수 선언, 배열 생성과 초기화 한번에
int[] students = new int[]{90, 80, 70, 60, 50};
// 배열의 편리한 초기화
int[] students = {90, 80, 70, 60, 50};
// 배열의 편리한 초기화 오류
int[] students;
students = {90, 80, 70, 60, 50};
8.5. 2차원 배열
· 2차원 배열은 행과 열로 구성된다.

public class ArrayDi {
public static void main(String[] args) {
// 2x3 2차원 배열을 만든다.
int[][] arr = new int[2][3]; //행(row), 열(column)
arr[0][0] = 1; //0행, 0열
arr[0][1] = 2; //0행, 1열
arr[0][2] = 3; //0행, 2열
arr[1][0] = 4; //1행, 0열
arr[1][1] = 5; //1행, 1열
arr[1][2] = 6; //1행, 2열
// 0행 출력
System.out.print(arr[0][0] + " "); // 0열 출력
System.out.print(arr[0][1] + " "); // 1열 출력
System.out.print(arr[0][2] + " "); // 2열 출력
System.out.println(); // 한 행이 끝나면 라인을 변경한다.
// 1행 출력
System.out.print(arr[1][0] + " "); // 0열 출력
System.out.print(arr[1][1] + " "); // 1열 출력
System.out.print(arr[1][2] + " "); // 2열 출력
System.out.println(); // 한 행이 끝나면 라인을 변경한다.
}
}
▶결과
1 2 3 // [0][0], [0][1], [0][2]
4 5 6 // [1][0], [1][1], [1][2]
8.6. 2차원 배열 리펙토링 - 초기화
// 2x3 2차원 배열, 초기화
int[][] arr = {
{1, 2, 3},
{4, 5, 6}
};
8.7. 향상된 for문 (Enhanced For Loop)
· 향상된 for문 정의
for (변수 : 배열 또는 컬렉션) {
// 배열 또는 컬렉션의 요소를 순회하면서 수행할 작업
}
· 일반 for문
//일반 for문
for(int i = 0; i < numbers.length; ++i) {
int number = numbers[i];
System.out.println(number);
}
· 향상된 for문
//향상된 for문, for-each문
for (int number : numbers) {
System.out.println(number);
}
· 향상된 for문을 사용할 수 없는 경우
- 인덱스 값을 직접 사용해야 하는 경우
// for-each문을 사용할 수 없는 경우, 증가하는 index 값 필요
for(int i = 0; i < numbers.length; ++i) {
System.out.println("number" + i + "번의 결과는: " + numbers[i]);
}
9. 메서드
9.1. 메서드 시작
· 함수 (function)

9.2. 메서드 사용
· 자바에서는 함수를 메서드(Method)라 한다.
· 메서드도 함수의 한 종류라고 생각하면 된다. 지금은 둘을 구분하지 않고, 이정도만 알아두자.
public class Method1Ref {
public static void main(String[] args) {
int sum1 = add(5, 10);
System.out.println("결과1 출력:" + sum1);
int sum2 = add(15, 20);
System.out.println("결과2 출력:" + sum2);
}
// add 메서드
public static int add(int a, int b) {
System.out.println(a + "+" + b + " 연산 수행");
int sum = a + b;
return sum;
}
}
▶결과
5+10 연산 수행
결과1 출력:15
15+20 연산 수행
결과2 출력:35
· 메서드는 크게 메서드 선언과 메서드 본문으로 나눌 수 있다.
· 메서드 선언(Method Declaration)
· public static int add(int a, int b)
- 메서드의 선언 부분으로, 메서드 이름, 반환 타입, 매개변수(파라미터) 목록을 포함한다.
- 이름 그대로 이런 메서드가 있다고 선언하는 것이다.
- 메서드 선언 정보를 통해 다른 곳에서 해당 메서드를 호출할 수 있다.
· public static
- public : 다른 클래스에서 호출할 수 있는 메서드라는 뜻이다. 접근 제어에서 학습한다.
- static : 객체를 생성하지 않고 호출할 수 있는 정적 메서드라는 뜻이다. 자세한 내용은 뒤에서 다룬다.
- 두 키워드의 자세한 내용은 뒤에서 다룬다. 지금은 단순하게 메서드를 만들 때 둘을 사용해야 한다고 생각하자.
· int add(int a, int b)
- int : 반환 타입을 정의한다. 메서드의 실행 결과를 반환할 때 사용할 반환 타입을 지정한다.
- add : 메서드에 이름을 부여한다. 이 이름으로 메서드를 호출할 수 있다.
- (int a, int b) : 메서드를 호출할 때 전달하는 입력 값을 정의한다. 이 변수들은 해당 메서드 안에서만 사용된다. 이렇게 메서드 선언에 사용되는 변수를 영어로 파라미터(parameter), 한글로 매개변수라 한다.
· 메서드 본문(Method Body)
{
System.out.println(a + "+" + b + " 연산 수행");
int sum = a + b;
return sum;
}
· 메서드가 수행해야 하는 코드 블록이다.
· 메서드를 호출하면 메서드 본문이 순서대로 실행된다.
· 메서드 본문은 블랙박스이다. 메서드를 호출하는 곳에서는 메서드 선언은 알지만 메서드 본문은 모른다.
· 메서드의 실행 결과를 반환하려면 return 문을 사용해야 한다. return 문 다음에 반환할 결과를 적어주면 된다.
- return sum : sum 변수에 들어있는 값을 반환한다.
· 메서드 호출이 끝나면 더 이상 해당 메서드가 사용한 메모리를 낭비할 이유가 없다. 메서드 호출이 끝나면 메서드 정의에 사용한 파라미터 변수인 int a, int b 는 물론이고, 그 안에서 정의한 int sum 도 모두 제거된다.
9.3. 메서드 호출과 용어정리
· 인수(Argument)
- 라는 용어는 '인’과 '수’의 합성어로, '들어가는 수’라는 의미를 가진다.
- 즉, 메서드 내부로 들어가는 값을 의미한다.
- 인자도 같은 의미이다.
- 실무에서는 아규먼트, 인수, 인자라는 용어를 모두 사용한다.
· 매개변수(Parameter)
- parameter는 '매개’와 '변수’의 합성어로, '중간에서 전달하는 변수’라는 의미를 가진다.
- 즉, 메서드 호출부와 메서드 내부 사이에서 값을 전달하는 역할을 하는 변수라는 뜻이다.
- 실무에서는 매개변수, 파라미터 용어를 모두 사용한다.
9.4. 메서드 정의
public static int add(int a, int b) {
// 메서드 본문, 실행 코드
}
제어자 반환타입 메서드이름(매개변수 목록) {
메서드 본문
}
· 제어자(Modifier): public , static 과 같은 부분이다. 제어자는 뒤에서 설명한다. 지금은 항상 public static 키워드를 입력하자.
· 반환 타입(Return Type): 메서드가 실행 된 후 반환하는 데이터의 타입을 지정한다. 메서드가 값을 반환하지 않는 경우, 없다는 뜻의 void 를 사용해야 한다. 예) void print(String str)
· 메서드 이름(Method Name): 메서드의 이름이다. 이 이름은 메서드를 호출하는 데 사용된다.
· 매개변수(Parameter): 입력 값으로, 메서드 내부에서 사용할 수 있는 변수이다. 매개변수는 옵션이다. 입력값이 필요 없는 메서드는 매개변수를 지정하지 않아도 된다. 예) add()
· 메서드 본문(Method Body): 실제 메서드의 코드가 위치한다. 중괄호 {} 사이에 코드를 작성한다.
9.5. 매개변수가 없거나 반환 타입이 없는 경우
· 매개변수가 없는 경우
- 선언: public static void printHeader() 와 같이 매개변수를 비워두고 정의하면 된다.
- 호출: printHeader(); 와 같이 인수를 비워두고 호출하면 된다.
· 반환 타입이 없는 경우
- 선언: public static void printHeader() 와 같이 반환 타입을 void 로 정의하면 된다.
- 호출: printHeader(); 와 같이 반환 타입이 없으므로 메서드만 호출하고 반환 값을 받지 않으면 된다.
String str = printHeader(); 반환 타입이 void 이기 때문에 이렇게 반환 값을 받으면 컴파일 오류가 발생한다.
9.6. 반환 타입
· 반환 타입이 있으면 반드시 값을 반환해야 한다.
· 반환 타입이 있는 메서드는 반드시 return 을 사용해서 값을 반환해야 한다.
· return 문을 만나면 그 즉시 메서드를 빠져나간다.
9.7. 메서드 호출과 값 전달
· 자바는 항상 변수의 값을 복사해서 대입한다.
public class MethodValue {
public static void main(String[] args) {
int num1 = 5;
System.out.println("1. changeNumber 호출 전, num1: " + num1);
changeNumber(num1);
System.out.println("4. changeNumber 호출 후, num1: " + num1);
}
public static void changeNumber(int num2) {
System.out.println("2. changeNumber 변경 전, num2: " + num2);
num2 = num2 * 2;
System.out.println("3. changeNumber 변경 후, num2: " + num2);
}
}
▶결과
1. changeNumber 호출 전, num1: 5
2. changeNumber 변경 전, num2: 5
3. changeNumber 변경 후, num2: 10
4. changeNumber 호출 후, num1: 5
· 메서드를 사용해서 값을 변경하려면 호출 결과를 반환 받아서 사용하면 된다.
public class MethodValue {
public static void main(String[] args) {
int num1 = 5;
System.out.println("changeNumber 호출 전, num1: " + num1); // 출력: 5
num1 = changeNumber(num1);
System.out.println("changeNumber 호출 후, num1: " + num1); // 출력: 10
}
public static int changeNumber(int num2) {
num2 = num2 * 2;
return num2;
}
}
▶결과
changeNumber 호출 전, num1: 5
changeNumber 호출 후, num1: 10
9.8. 메서드와 형변환
· 메서드를 호출할 때도 형변환이 적용된다.
· 명시적 형변환
public class MethodCasting {
public static void main(String[] args) {
double number = 1.5;
// printNumber(number); // double을 int형에 대입하므로 컴파일 오류
printNumber((int) number); // 명시적 형변환을 사용해 double을 int로 변환
}
public static void printNumber(int n) {
System.out.println("숫자: " + n);
}
}
· 자동 형변환
- int < long < double
- 메서드를 호출할 때 매개변수에 값을 전달하는 것도 결국 변수에 값을 대입하는 것이다. 따라서 자동 형변환이 그대로 적용된다.
public class MethodCasting2 {
public static void main(String[] args) {
int number = 100;
printNumber(number); // int에서 double로 자동 형변환
}
public static void printNumber(double n) {
System.out.println("숫자: " + n);
}
}
9.9. 메서드 오버로딩
· 두 수를 더하는 메서드, 세 수를 더하는 메서드를 만들고 싶다.
· 이 경우 둘다 더하는 메서드이기 때문에 가급적 같은 이름인 add 를 사용하고 싶다.
· 자바는 메서드의 이름 뿐만 아니라 매개변수 정보를 함께 사용해서 메서드를 구분한다.
· 따라서 다음과 같이 이름이 같고, 매개변수가 다른 메서드를 정의할 수 있다.
· 오버로딩 성공
add(int a, int b)
add(int a, int b, int c)
add(double a, double b)
· 오버로딩 실패
int add(int a, int b)
double add(int a, int b)
· 메서드 시그니처(method signature)
· 메서드 시그니처 = 메서드 이름 + 매개변수 타입(순서)
- 메서드 시그니처는 자바에서 메서드를 구분할 수 있는 고유한 식별자나 서명을 뜻한다.
- 메서드 시그니처는 메서드의 이름과 매개변수 타입(순서 포함)으로 구성되어 있다.
- 쉽게 이야기해서 메서드를 구분할 수 있는 기준이다.
- 자바 입장에서는 각각의 메서드를 고유하게 구분할 수 있어야한다.
- 그래야 어떤 메서드를 호출 할 지 결정할 수 있다.
- 따라서 메서드 오버로딩에서 설명한 것 처럼 메서드 이름이 같아도 메서드 시그니처가 다르면 다른 메서드로 간주한다.
- 반환 타입은 시그니처에 포함되지 않는다.
- 방금 오버로딩이 실패한 두 메서드를 보자.
- 두 메서드는 add(int a, int b) 로 메서드 시그니처가 같다.
- 따라서 메서드의 구분이 불가능하므로 컴파일 오류가 발생한다.
9.10. 메서드 사용의 장점
· 코드 재사용
- 메서드는 특정 기능을 캡슐화하므로, 필요할 때마다 그 기능을 다시 작성할 필요 없이 해당 메서드를 호출함으로써 코드를 재사용할 수 있다.
· 코드의 가독성
- 이름이 부여된 메서드는 코드가 수행하는 작업을 명확하게 나타내므로, 코드를 읽는 사람에게 추가적인 문맥을 제공한다.
· 모듈성
- 큰 프로그램을 작은, 관리 가능한 부분으로 나눌 수 있다. 이는 코드의 가독성을 향상시키고 디버깅을 쉽게 만든다.
· 코드 유지 관리
- 메서드를 사용하면, 코드의 특정 부분에서 문제가 발생하거나 업데이트가 필요한 경우 해당 메서드만 수정하면 된다. 이렇게 하면 전체 코드 베이스에 영향을 주지 않고 변경 사항을 적용할 수 있다.
· 재사용성과 확장성
- 잘 설계된 메서드는 다른 프로그램이나 프로젝트에서도 재사용할 수 있으며, 새로운 기능을 추가하거나 기존 기능을 확장하는 데 유용하다.
· 추상화
- 메서드를 사용하는 곳에서는 메서드의 구현을 몰라도 된다. 프로그램의 다른 부분에서는 복잡한 내부 작업에 대해 알 필요 없이 메서드를 사용할 수 있다.
· 테스트와 디버깅 용이성
- 개별 메서드는 독립적으로 테스트하고 디버그할 수 있다. 이는 코드의 문제를 신속하게 찾고 수정하는 데 도움이 된다.