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.