본문 바로가기
Java & Spring

Java NumberFormatException 에 대처하는 우리들의 자세

by softserve 2021. 10. 27.
반응형

NumberFormatException(이하, NFE)은 숫자가 아닌 것을 숫자로 바꾸려고 하는 경우를 말합니다.

 

주로 문자열을 Integer.parseInt()를 이용해 int형으로 바꿀 때 발생합니다.

 

사례 1. Data type 의 범위를 넘어서는 경우


int 타입은 –2,147,483,648 ~ 2,147,483,647 까지의 숫자를 표현할 수 있습니다.

 

만약 String s = "12,147,483,648"를 int로 바꾸려고 한다면 int형의 범위를 넘어서게 되므로 NFE가 발생합니다.

 

해결방법

 

long 을 씁니다.

long의 범위는 –9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 입니다.

 

만약 long보다 긴 경우는?

 

BigInteger 클래스를 이용합니다.

 

import java.math.BigInteger;

public class Main{
	
	public static void main(String[] args){
	
		String s1 = "1212312123123312312312312312313123141231234123";
		String s2 = "1212312123123312312312312312313123141231234124";
		BigInteger b1 = new BigInteger(s1);
		BigInteger b2 = new BigInteger(s2);
		
        int i = Integer.parseInt(s1); //NFE

		int l = Long.parseLong(s1); //NFE

		if(b2.compareTo(b1)==1) System.out.println("s2가 s1보다 크다");
		
	}

}

 

사례 2. Scanner를 잘못 이용하는 경우

입력을 처리하기 위한 Scanner 클래스에는 다음과 같은 메소드들이 있습니다.

 

nextInt()는 숫자를 읽어들입니다. 숫자가 아닌 것, 공백이나 개행문자(\n)를 만나면 읽기를 중단합니다.

next()는 \n를 골라내고 맛있는 것만 먹은 다음, String으로 반환해줍니다.
nextLine()는 \n 까지도 먹어치웁니다. 하지만 String을 반환할 때에는 \n을 뱉어냅니다.

 

import java.util.Scanner;

class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
        
        int a = sc.nextInt();
        String s = sc.nextLine();
        int b = Integer.parseInt(s); //NFE
        
	}
}

input

10 ↵

output

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at Main.main(Main.java:9)

위의 예와 같이 사용자가 10과 엔터를 입력하면

 

① nextInt()는 10을 먹고 nextLine()이 \n 을 먹습니다.

 

② nextLine()이 s에게 문자열을 반환할 때는 \n를 뱉어내기 때문에 s는 "" 공백상태가 됩니다.

 

③ 따라서 parseInt가 s를 보는 순간 "너는 숫자가 아니다!" 라고 외치면서 분노에 찬 NFE를 날리는 것입니다.

해결방법

위와 같은 경우에는 nextLine() 대신 next()를 사용하거나,

 

사용자의 엔터가 예상될 때에는 nextLine()을 하나 더 사용해서 \n를 처리해줍니다.

 

import java.util.Scanner;

class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
        
        int a = sc.nextInt();
        //String s = sc.next();
        sc.nextLine();
        String s = sc.nextLine();
        
        int b = Integer.parseInt(s);
        
        System.out.println(b);        
	}
}


사례 3 숫자가 아닌 문자열을 parseInt()에 집어넣는 경우

import java.util.Scanner;

class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
        
        String s = sc.next();
        
        int a = Integer.parseInt(s);
	}
}

위 예제에는 별로 이상이 있어 보이지는 않습니다.
숫자를 입력하면 쓸데없이 문자열로 받았다가 숫자로 바꿔서 출력해줍니다. 

 

하지만 문제는 사용자가 숫자를 입력해주리라는 보장이 없다는 것입니다.

 

아무리 숫자만 넣으라고 그렇게 얘기를 해도 굳이 숫자를 넣어보려는 사람이 있습니다. 오타의 가능성도 있습니다.

 

해결방법

 

그래서 예외처리를 해줘야 합니다.

 

import java.util.Scanner;

class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
	        
		while(true) {
	        System.out.println("숫자를 입력하시오");
			String s = sc.next();
	        int a=0;
			
			try {
				a = Integer.parseInt(s);
			}
			catch (NumberFormatException e) {
				System.out.println("숫자만 입력하라고");
			}
	        
			if(a!=0) {
				System.out.println("당신이 입력한 숫자는 " + a + "입니다.");
			}
		}
	}
}

 

숫자를 입력하시오
> 1234
당신이 입력한 숫자는 1234입니다.
숫자를 입력하시오
> abcd
숫자만 입력하라고
반응형

댓글