Scanner 클래스는 Java에서 표준 입력 (키보드 입력)을 처리하기 위해 제공되는 유틸리티 클래스입니다. 주로 사용자가 데이터를 입력할 수 있도록 설계된 프로그램에서 사용됩니다. java.util 패키지에 포함되어 있으며, 다양한 데이터 타입의 입력을 처리할 수 있습니다.
1. Scanner 클래스의 기본 개념
- Scanner는 Java의 표준 입력 스트림(System.in)을 통해 데이터를 읽습니다.
- 사용자가 입력한 문자열을 파싱하여 원하는 데이터 타입으로 변환할 수 있습니다.
- 공백(스페이스, 탭, 줄바꿈) 단위로 데이터를 구분하여 입력을 처리합니다.
2. Scanner 클래스 사용법
기본 구조
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// Scanner 객체 생성
Scanner scanner = new Scanner(System.in);
// 정수 입력받기
System.out.print("정수를 입력하세요: ");
int num = scanner.nextInt();
System.out.println("입력된 정수: " + num);
// 문자열 입력받기
System.out.print("문자열을 입력하세요: ");
String str = scanner.next();
System.out.println("입력된 문자열: " + str);
// Scanner 객체 닫기
scanner.close();
}
}
3. 주요 메서드
Scanner 클래스는 입력 데이터를 다양한 타입으로 읽기 위한 여러 메서드를 제공합니다.
메서드설명예시
nextInt() | 정수를 입력받습니다. | int num = scanner.nextInt(); |
nextDouble() | 실수를 입력받습니다. | double num = scanner.nextDouble(); |
nextLine() | 한 줄의 문자열을 입력받습니다. | String line = scanner.nextLine(); |
next() | 공백을 기준으로 한 단어를 입력받습니다. | String word = scanner.next(); |
hasNextInt() | 다음 입력값이 정수인지 확인합니다. | if(scanner.hasNextInt()) |
hasNextDouble() | 다음 입력값이 실수인지 확인합니다. | if(scanner.hasNextDouble()) |
hasNextLine() | 다음 줄이 존재하는지 확인합니다. | if(scanner.hasNextLine()) |
4. 주요 특징과 유의점
1) next() vs nextLine()
- next()는 공백(스페이스, 탭, 줄바꿈)을 기준으로 한 단어를 읽습니다.
- nextLine()은 줄바꿈을 포함하여 한 줄 전체를 읽습니다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("next() 사용: ");
String word = scanner.next();
System.out.println("입력된 단어: " + word);
scanner.nextLine(); // 버퍼 비우기
System.out.print("nextLine() 사용: ");
String line = scanner.nextLine();
System.out.println("입력된 줄: " + line);
scanner.close();
}
}
출력 예시:
next() 사용: Hello World
입력된 단어: Hello
nextLine() 사용: 입력된 줄: World
2) 입력 버퍼 문제
- nextInt()와 nextLine()을 함께 사용할 때, nextInt() 뒤에 nextLine()을 호출하면 버퍼에 남아있는 줄바꿈 문자(\n) 때문에 문제가 발생할 수 있습니다.
해결 방법:
scanner.nextLine(); // 추가로 호출하여 버퍼를 비운다.
5. 실용적인 예제
정수와 문자열 입력
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("나이를 입력하세요: ");
int age = scanner.nextInt();
scanner.nextLine(); // 버퍼 비우기
System.out.print("이름을 입력하세요: ");
String name = scanner.nextLine();
System.out.println("나이: " + age + ", 이름: " + name);
scanner.close();
}
}
여러 개의 데이터 읽기
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("공백으로 구분된 숫자 3개를 입력하세요:");
int num1 = scanner.nextInt();
int num2 = scanner.nextInt();
int num3 = scanner.nextInt();
System.out.println("입력된 숫자: " + num1 + ", " + num2 + ", " + num3);
scanner.close();
}
}
6. Scanner를 사용할 때의 주의점
- Scanner 객체 닫기
- 프로그램이 끝날 때 scanner.close()를 호출하여 자원을 해제해야 합니다.
- 단, System.in을 사용하는 경우 프로그램에서 다른 곳에서 입력을 처리한다면 close()를 호출하지 않는 것이 좋습니다.
- 입력 형식 오류
- 사용자가 입력 형식에 맞지 않는 데이터를 입력하면 InputMismatchException이 발생할 수 있습니다.
- 이를 방지하기 위해 hasNextInt()와 같은 메서드를 사용하여 데이터의 유효성을 먼저 확인하는 것이 좋습니다.
7. Scanner와 관련된 실생활 비유
- Scanner는 키보드에서 입력을 읽는 스캐너 기계와 비슷합니다.
- 스캐너가 책의 텍스트를 읽고 필요한 정보를 전달하듯, Scanner 클래스는 키보드에서 입력한 데이터를 읽고 원하는 형태로 변환합니다.
Scanner scanner = new Scanner(System.in);
이 한 줄의 코드는 Java에서 표준 입력(주로 키보드 입력)을 처리하기 위해 사용되는 문장입니다. 이 문장을 하나씩 분석해서 상세히 설명하겠습니다.
1. Scanner
(1) 클래스 이름
- Scanner는 Java의 표준 라이브러리 중 하나로, 입력 데이터를 처리하는 데 사용되는 클래스입니다.
- java.util 패키지에 포함되어 있으므로 import java.util.Scanner; 문이 필요합니다.
(2) 역할
- 사용자로부터 입력받은 데이터를 읽어오고, 이를 다양한 데이터 타입(int, double, String 등)으로 변환할 수 있습니다.
- 파일, 문자열 등 다양한 입력 소스도 처리할 수 있지만, 여기서는 키보드 입력(System.in)에만 집중합니다.
2. scanner
(1) 변수 이름
- scanner는 Scanner 클래스의 객체를 참조하는 변수입니다.
- 프로그래머가 자유롭게 이름을 정할 수 있으며, scanner는 관용적으로 많이 사용되는 이름입니다.
(2) 역할
- scanner는 Scanner 객체를 메모리에 생성하고 이를 통해 입력 데이터를 처리할 수 있게 합니다.
- 이후 scanner.nextInt(), scanner.nextLine() 등의 메서드를 호출하여 입력 데이터를 읽습니다.
3. new
(1) 키워드
- new는 Java에서 객체를 생성할 때 사용하는 키워드입니다.
- 이 키워드는 메모리 힙(heap) 영역에 객체를 생성하고 해당 객체의 참조를 반환합니다.
(2) 역할
- new Scanner(System.in)은 Scanner 클래스의 생성자를 호출하여 새로운 Scanner 객체를 만듭니다.
4. Scanner(System.in)
(1) 생성자 호출
- Scanner 클래스의 생성자는 다양한 입력 소스를 처리할 수 있도록 설계되어 있습니다.
- 이 경우, System.in을 매개변수로 전달하여 표준 입력 스트림(키보드 입력)을 입력 소스로 사용하는 객체를 생성합니다.
public Scanner(InputStream source) {
// 표준 입력 소스를 초기화하는 코드
}
(2) System.in
- 표준 입력 스트림으로, 키보드로부터 입력 데이터를 받을 수 있습니다.
- Java의 System 클래스는 표준 입출력을 처리하는 정적 멤버를 제공합니다:
- System.out : 표준 출력 스트림 (화면에 출력)
- System.err : 표준 에러 스트림 (에러 메시지 출력)
- System.in : 표준 입력 스트림 (키보드 입력 처리)
전체 흐름
1) 메모리 관점
- Scanner scanner 선언: 메모리에 참조 변수를 생성합니다.
- new Scanner(System.in): 힙 영역에 Scanner 객체를 생성하고, 입력 소스로 System.in을 설정합니다.
- scanner 변수: 생성된 Scanner 객체를 참조합니다.
2) 실행 순서
- System.in이 Scanner 생성자의 매개변수로 전달됩니다.
- Scanner 객체는 System.in을 입력 소스로 사용하는 준비를 마칩니다.
- 이후 scanner.nextInt()와 같은 메서드를 호출하여 사용자가 입력한 데이터를 읽습니다.
비유로 설명
- Scanner: 데이터(입력)를 읽는 장치. 키보드로 입력된 데이터를 스캔합니다.
- scanner: 스캐너 기계를 참조하는 리모컨. 이 리모컨으로 명령(nextInt(), nextLine())을 내립니다.
- new: 새로운 스캐너를 가져오는 주문서. 메모리에 새로운 스캐너를 요청합니다.
- System.in: 스캐너가 데이터를 읽을 책. 여기서는 키보드 입력이 데이터의 소스입니다.
코드 예제로 확인
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// Scanner 객체 생성
Scanner scanner = new Scanner(System.in);
// 정수 입력
System.out.print("정수를 입력하세요: ");
int number = scanner.nextInt();
System.out.println("입력된 정수: " + number);
// 문자열 입력
scanner.nextLine(); // 버퍼 비우기
System.out.print("문자열을 입력하세요: ");
String text = scanner.nextLine();
System.out.println("입력된 문자열: " + text);
// Scanner 객체 닫기
scanner.close();
}
}
실행 예시
정수를 입력하세요: 25
입력된 정수: 25
문자열을 입력하세요: Hello World
입력된 문자열: Hello World
추가로 알아두면 좋은 내용
1. Scanner는 버퍼를 사용
- Scanner는 입력 데이터를 버퍼라는 임시 저장 공간에 저장한 후 처리합니다.
- 여러 입력 메서드를 섞어서 사용할 때 버퍼에 남아 있는 데이터를 주의해야 합니다.
2. Scanner를 닫아야 하는 이유
- scanner.close()는 System.in 스트림을 닫습니다.
- 입력 처리가 끝난 후 스트림을 닫는 것은 자원을 효율적으로 관리하기 위함입니다.
이 키워드는 메모리 힙(heap) 영역에 객체를 생성하고 해당 객체의 참조를 반환합니다.
이 말이 무슨 말인지?
이 문장은 new 키워드의 역할을 설명한 것입니다. Java에서 new 키워드는 객체를 생성할 때 사용하는 키워드이며, 객체가 메모리의 특정 영역인 힙(heap) 영역에 생성된다는 것을 의미합니다. 아래에서 하나씩 상세히 설명하겠습니다.
1. 힙(heap) 영역이란?
- 힙 메모리는 Java 프로그램 실행 중에 **런타임(runtime)**에 동적으로 생성된 객체를 저장하는 메모리 영역입니다.
- JVM(Java Virtual Machine)의 메모리 영역은 보통 크게 나뉩니다:
- 스택(stack):
- 메서드 호출, 지역 변수, 참조 변수 등을 저장.
- 빠르게 할당되고 해제되며, 메모리 크기가 고정적.
- 힙(heap):
- 객체와 배열이 저장되는 동적 메모리 영역.
- 객체는 필요하지 않을 때까지 힙에 남아 있으며, **가비지 컬렉터(Garbage Collector)**에 의해 자동으로 제거됩니다.
- 스택(stack):
2. new 키워드의 역할
(1) 객체 생성
- new 키워드는 힙 영역에 객체를 생성합니다.
- 이 객체는 클래스의 **생성자(Constructor)**를 호출하여 초기화됩니다.
(2) 참조 반환
- new 키워드는 생성된 객체의 **메모리 주소(참조값)**를 반환합니다.
- 이 참조값은 변수(예: scanner)에 저장되며, 이후 이 변수로 해당 객체에 접근할 수 있습니다.
3. 과정 상세히 분석
예제 코드
Scanner scanner = new Scanner(System.in);
위 코드를 실행하면 다음 단계를 거칩니다:
- 힙 영역에 객체 생성
- new Scanner(System.in)을 호출하면 Scanner 클래스의 객체가 힙(heap) 메모리 영역에 생성됩니다.
- 참조값 반환
- 생성된 객체의 메모리 주소(참조값)가 반환됩니다.
- 참조 변수에 저장
- 반환된 참조값이 scanner 변수에 저장됩니다.
- 이제 scanner를 통해 힙에 있는 Scanner 객체에 접근할 수 있습니다.
4. 힙 메모리와 스택 메모리의 역할
예제 코드의 메모리 구조
Scanner scanner = new Scanner(System.in);
- 스택(stack):
- scanner라는 변수는 스택 메모리에 저장됩니다.
- 이 변수는 힙에 생성된 Scanner 객체의 참조값을 저장합니다.
- 힙(heap):
- new Scanner(System.in)에 의해 힙 메모리에 Scanner 객체가 생성됩니다.
- 이 객체는 키보드 입력을 처리할 수 있도록 초기화됩니다.
시각적 구조:
스택 메모리 힙 메모리
+----------------+ +-----------------+
| scanner | -----> | Scanner 객체 |
+----------------+ +-----------------+
5. 객체가 사라지는 시점
가비지 컬렉션(Garbage Collection)
- Java에서는 프로그래머가 직접 메모리를 관리하지 않고, **가비지 컬렉터(GC)**가 사용되지 않는 객체를 자동으로 제거합니다.
- 참조 변수(scanner)가 더 이상 객체를 참조하지 않으면 해당 객체는 **가비지(garbage)**로 간주되고, 힙에서 제거됩니다.
scanner = null; // 참조를 끊음
// 이후 가비지 컬렉터가 힙 메모리에서 Scanner 객체를 제거
6. 비유로 이해
- new는 공장에서 새 제품을 만드는 과정과 같습니다.
- 공장에서 새 제품(객체)을 만들면, 창고(힙 메모리)에 저장됩니다.
- 물류 센터(스택 메모리)는 이 제품의 위치(참조값)를 기억합니다.
- 프로그램이 끝나거나 더 이상 사용하지 않으면 청소부(가비지 컬렉터)가 창고에서 이 제품을 치웁니다.
7. 결론
new 키워드는:
- 힙 메모리에 새로운 객체를 생성합니다.
- 객체의 참조값(메모리 주소)을 반환합니다.
- 반환된 참조값은 참조 변수(예: scanner)에 저장되어 객체에 접근할 수 있게 합니다.