Java 입력을 얻기 위해 스캐너 클래스의 인스턴스가 필요한 이유는 무엇입니까?


10

Java는 객체 지향적이지만 입력을 얻기 위해 스캐너 클래스에서 객체를 만들어야하는 이유는 무엇입니까? 할 수 없습니다 next()방법은, 예를 들어, 단지 정적?

C 나에게 당신은 그냥 사용으로 아주 간단하게 보이는 scanf(), gets()또는 fgets(). Java 개발자가 Scanner 클래스를 작성해야 할 이유가 있다고 확신하지만 정상적인 기능을 수행하는 것보다 더 나은 방법은 무엇입니까?

같은 질문을하는 것처럼 보일 수있는 이 링크 를 찾았 지만 답변은 거의

"정적이 아니기 때문에 객체를 만들어야합니다"...

내 추측은 : Java는 객체 지향이기 때문에 모든 입력 방법을 클래스에 넣기로 결정했습니다. 그들은 정적 메소드를 수행하지 않았으므로 다른 객체에 모든 종류의 다른 소스 (키보드 입력, 파일 입력 ...)를 가질 수 있습니까?

더 명확하게 들리도록 질문을 편집 할 수 있다면 고맙겠습니다.

답변:


34

대답은 "스캐너에 상태가 있기 때문"입니다.

java.util.Scanner코드를 보면 버퍼 및 관련 정보, Matcher, Pattern, 입력 소스, 소스가 닫혔는지 여부에 대한 정보, 유형과 같은 여러 개인 필드가 표시됩니다. 마지막 항목 일치, 마지막 항목이 유효한 일치 여부에 대한 정보, 숫자에 사용 된 기수, 로케일 (사용 .하거나 ,수천 구분 기호로 사용중인 경우에 대한 정보 ) 및 최근에 사용한 패턴에 대한 자체 LRU 캐시 , 마지막으로 발생한 예외에 대한 정보, 구문 분석 숫자에 대한 정보, 부울 구문 분석에 대한 정보, 정수 구문 분석에 대한 약간의 추가 정보 ... 그리고 그것에 대해 생각합니다.

보시다시피, 그것은 상당히 큰 텍스트 블록입니다. 이것이 스캐너의 상태입니다. 검사기를 정적 클래스로 만들려면 해당 상태를 다른 곳에 저장해야합니다. 그것을하는 C 방식에는 실제로 그렇게 많은 상태가 없습니다. 당신은 fscanf있습니다. FILE은 현재 위치에 대한 상태를 유지합니다 (그러나 각 호출마다 전달되어야 함 fscanf). 오류가 발생하면 처리해야합니다 (그리고 다음과 같은 코드 작성을 시작 하십시오 ). "정수를 기대했지만 문자열을 찾았습니다."와 같은 정보를 알려주지 않습니다.

이론적으로 정적 인 스캐너를 살펴보면 모든 상태가 클래스 외부에서 유지 관리되며 클래스 내에서 캡슐화되지 않습니다. 다른 코드의 비트는 이러한 변수에 영향을 줄 수 있습니다. 다른 코드가 클래스의 상태에 어설픈 경우, 주어진 상황에서 클래스가 무엇을할지 추론하기가 매우 어려워집니다.

아마도 다음과 같은 것을 작성하고 ScannerState { Locale loc; ... }코드를 만들 수 있습니다.

ScannerState state = new ScannerState(a whole lot of arguments);
int foo = Scanner.nextInt(state);

그러나 이것은 상태가 처음에 스캐너 개체 내에 캡슐화되어있는 상태보다 훨씬 번거 롭습니다 (상태를 전달할 필요는 없음).

마지막으로, 스캐너는 다음 Iterator<String>과 같은 코드에서 사용할 수 있는 인터페이스를 구현합니다 .

Scanner in = new Scanner(someFile);
whie(in.hasNext()) { ... }

Scanner 클래스의 인스턴스를 얻을 수 없으면이 유형의 구조는 객체 지향 언어 내에서 더 번거로워집니다.


1
InputStream은 스캐너뿐만 아니라 상태도 있지만 작성한 모든 내용은 절대적으로 사실입니다. C와 같이 입력이 콘솔에서 오는 경우 입력을 시작하기 위해 매개 변수를 전달할 필요가 없습니다. 상태 필요한 다른 스트림이 수행되는 방식과 일치하도록이 방법으로 수행되었다고 가정합니다 .
Neil

@Neil InputStream FILE*은 C 의 (위치 상태) 와 동일합니다 .
ratchet freak

1
스캐너는 구현 Iterator하지 않습니다 Iterable. Enhanced-for 루프에서는 스캐너를 사용할 수 없습니다.
turbanoff

@ratchetfreak 정확하게. 그것이 "상태"FileInputStreams가 가지고 있어야하는 것이지만, 이미 기술적으로 열려 있기 때문에 콘솔로부터의 입력에는 적용되지 않습니다.
Neil

1
@turbanoff 저를 불러 주셔서 감사합니다. 나는 그것을 고쳤다.

7

짧은 대답 : 당신은하지 않습니다. 스캐너 인스턴스를 사용하지 않고도 사용자 입력을 얻을 수 있습니다.
예를 들면 다음과 같습니다. https://docs.oracle.com/javase/tutorial/essential/io/cl.html 또는
http://alvinalexander.com/blog/post/java/java-source-code-read-command-line -입력


String orgName = (new BufferedReader(new InputStreamReader(System.in))).readLine();a를 사용하는 것에 비해 엄청나게 복잡 Scanner하고 하나만 아니라 두 개의 객체로 된 새로운 인스턴스를 만들어 즉시 버립니다.
Philipp

2
@Philipp, 1) 번거롭지 만 확실히 대안이며 2) 인스턴스를 즉시 버리는 경우 잘못된 일을하고 있습니다 (또는 콘솔에서 한 줄만 읽으면됩니다).
Arturo Torres Sánchez

입력을 읽기 위해 스캐너가 필요하지 않습니다. 또한 InputStreamReader가 필요하지 않으며 BufferedReader가 필요하지 않습니다. C에서와 마찬가지로 System.in에서 "원시"스트림으로 작업 할 수 있습니다. 스캐너는 해당 스트림을 사용하는 매우 편안한 방법입니다.
Traubenfuchs 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.