(Java)Scanner next(), nextLine 차이

필자는 오류를 만나기 전까지 Scanner클래스의 next()와 nextLine의 차이에 대해 정확히 알지 못 했다.

 

그러다 next()와 nextLine을 혼용하여 쓰던 중 오류를 만나 둘의 차이에 대해 알아보고 글을 쓰게 되는 계기가 되었다.

 

Scanner 클래스의 next(), nextLine은 어떤 차이가 있을까?

 

둘을 혼용해서 사용했을 경우 왜 예상결과와 다른 결과가 출력이 될 까?

 

지금부터 위의 질문에 대한 답변을 할 수 있도록 두 메소드에 대해 자세히 알아보도록 하자

 


1. Scanner클래스

우선 스캐너 클래스부터 살펴보자

 

스캐너 클래스의 특징은 아래와 같다.

  • 스캐너 클래스는 토큰 단위로 값을 읽어 들인다
  • 토큰이란 공백문자 즉 스페이스바, 탭, 엔터 등 문자를 구분 짓는 것을 일컫는다
  • 입력받은 문자열은 버퍼라는 저장소에 저장된다.
  • 버퍼 저장소에는 문자열만 저장 되는 것이 아닌 각 토큰 즉 공백, 개행, 엔터 등이 문자열과 함께 저장된다
  • 문자열을 버퍼로부터 읽어 들일 때는 각 메서드의 토큰 단위로 문자열을 읽어 들이게 된다.

위의 내용을 바탕으로 우리가 생선한 스캐너 클래스로 next() 메소드를 호출할 때 실행흐름을 살펴보자

  1.  next()를 호출 받으면 사용자로부터 입력값을 받을 때 까지 대기하게 된다.
  2.  사용자가 값을 입력하면 입력된 문자는 버퍼에 저장된다. 이때 \n과 엔터도 같이 저장이 된다.
  3.  입력된 문자를 next()가 읽어 오게 되는데 위에서 설명한 바와 같이 토큰 단위로 문자를 읽어 들인다.
  4.  즉 next()는 \n(공백)을 기준으로 문자를 읽어 들이므로 \n이전의 문자까지만 읽는다
  5.  여전히 버퍼저장소에는 \n과 엔터가 남아있는 상태이다.

큰 실행흐름은 위와 같다.

 

그러므로 이제부터 알아보고자 하는 것은 "next()와 nextLine()이  각각 어떤 토큰 단위를 기준으로 문자열을 읽는가"라는 것에 중점을 두고 살펴보고자 한다.


2. next()

next()는 next(), nextByte(), nextInt(), nextDouble()와 같이 "next + type"을 조합하여 사용한다.

아래의 예제 그림을 통해 특징을 살펴보자

next() 예제

위의 그림과 같이 코드가 작성 되어 있을 때 입력 값으로 "we are the one"을 입력하면 어떻게 결과가 출력 될까?

결과

결과는 위와 같이 공백을 기준으로 단어를 하나씩 input1~input4에 저장하여 공백없이 출력하게 된다.

 

결과에서 알 수 있듯이 next()는 \n(공백) 즉 스페이스바를 한 기준으로 \n(개행) 앞 까지만 읽어 들이게 된다.

그리고 버퍼에 저장 돼 있는 \n과 Enter는 리턴하지 않고 여전히 버퍼저장소에 남아 있는 상태가 된다.

input2에서는 are을 입력하게 되면 이전 input1에서 입력받고 남은 \n과 엔터는 읽어 들이지 않고 입력된 are까지만 읽고 \n을 만나 앞에서와 같이 \n전 are까지만 읽어 들이게 되는 것이다.

 

특징을 간단하게 정리해 보자

  • next()는 \n(개행) 전 까지만 문자를 읽어 들인다
  • 읽어 들일 문자는 return하고, 버퍼 저장소에는 여전히 \n과 Enter는 남아 있는 상태이다
  • 다음 next()를 만나면 next()는 \n은 읽어 들이지 않기 때문에 \n과 Enter를 무시하고 다음 문자를 읽어 들인다

3. nextLine()

이번에는 nextLine()을 next()예제의 코드를 약간 변경하여 알아보자

 

nextLine() 예제

이전과 다르게 nextLine()을 한줄만 작성하고 "we are the one" 문자열을 공백을 포함하여 입력하면 어떻게 출력이 될까?

결과

위의 결과에서 알 수 있듯이 공백을 포함하여 입력한 문자열이 그대로 출력된 것을 확인 할 수 있다.

 

그럼 nextLine()의 특징을 정리해 보자

  • nextLine()은 next()와 다르게 \n(공백)을 포함하여 문자열을 읽는다
  • 즉 공백을 기준으로 문자를 읽어 들이는 것이 아닌 Enter를 기준으로 문자를 읽는다

큰 특징은 이와 같이 정리 할 수 있겠다.

 

next(), nextLine의 차이점 정리)

next()와 nextLine의 가장 큰 차이는 next()는 공백을 기준으로  문자를 읽어 들이고 버퍼에 \n과 엔터가 남게된다는 것. nextLine은 문자열과 공백을 같이 읽어 들이고 Enter를 기준으로 문자를 읽어 들인다는 것이 둘의 가장 큰 차이점이다.


4. next()와 nextLine()을 혼용해서 사용할 때의 문제점

그렇다면 둘을 혼용 해서 사용했을 경우 어떠한 문제점이 발생할까?

 

next()와 nextLine()의 혼용

위와 같은 코드에서 3개의 입력값을 받으려고 한다. 각각 "we" "are" "win"이라는 문자열을 각각 입력하려고 했을 때 아마 출력 결과가 각각의 단어가 예상대로 나올 것 이라고 착각하기 쉽다.

아래의 결과를 보자

결과

결과는 위와 같이 we are까지만 입력하고 다음 input3은 자동으로 공백이 출력되고 main메소드가 종료된다.

 

이유는 앞서 설명한 바와 같이 앞의 input2에서 문자를 저장할 때 are을 버퍼에 저장할 때 \n과 Enter가 같이 저장이 되었고 next()가 읽어 들일 때 \n(공백)이전 까지만 읽어 들여 여전히 버퍼에는 \n과 Enter가 남아있는 상태이다.

그렇기 때문에 input3에서 버퍼에 남아 있던 \n과 Enter를 만나 자동 출력하여 예상과 다르게 출력된 것을 확인 할 수 있다.

 

이렇게 next()와 nexLine()을 혼용하여 쓸 때 위와 같은 상황을 방지하기 위해서는 아래와 같이 코드를 작성하면 된다

기존의 코드에서 sc.nextLine()을 추가하여 \n과 Enter을 제거하고 다음 줄에서 sc.nextLine()으로 출력하는 방법이다.

이와 같이 작성하면 기존의 예상대로 정상 출력되는 것을 확인 할 수 있다. 


✏️마무리하며

지금까지 next()와 nextLine의 차이점에 대해서 알아보았다.

아마 이 글을 작성하기 전에 이러한 시행착오를 겪지 않았다면 아마 지금까지도 둘의 차이점을 모르고 그냥 편한 것을 사용했을 것이다.

에러를 만남으로써 두 메서드의 차이와 Scanner에 대해서 조금은 더 상세하게 알 수 있는 좋은 계기가 되었고 앞으로 공부함에 있어서 문제해결능력을 키우는데 좋은 밑거름이 되었으면 한다.

'Java' 카테고리의 다른 글

(Java) Object toString()  (0) 2022.05.23
(Java) syntax error: insert } to complete ClassBody  (0) 2022.05.23
(Java) 논리 연산자 &,&& 와 |,|| 차이  (0) 2022.05.23
(Java)JVM 메모리 구조  (0) 2022.05.06
(Java)Compiler  (0) 2022.05.06