백준 1152번 단어의 개수 문제에서 string.split() 을 이용하여 제출했는데 틀렸다고 나와 디버깅을 하던 중 String에 대해 알게 된 사실이 있어 적어본다.
공백이 포함된 문장이 주어지고, 공백을 기준으로 그 문장에서 단어가 몇 개 있는지를 세는 문제이다.
String[] arr = str.split(" ");
System.out.print(arr.length);
위 코드대로 작성하고 제출하니 잘 진행되는가 싶다가 실패 결과가 나왔다.
아마 테스트 케이스에서 앞 뒤에 공백이 존재할 수 있다는 부분 때문에 문제가 생긴 것 같아 디버깅 해보니
(공백)test case(공백)
결과 : 3
이렇게 나오는 것이 아닌가?
split으로 쪼개진 arr 내부를 살펴보니
[0] : " ", [1] : test, [2] : case
이런 식으로 맨 앞의 공백은 제거가 되지 않은채 배열에 저장되었다.
이 부분은 왜 그런 것인지 아무리 찾아봐도 원인을 알 수 없었다. split의 내부 동작 방식을 봐야 알 것 같은데, 그건 좀;;;
어쩔 수 없이 String.trim() 을 이용하여 앞 뒤 공백을 제거하여 가공한 뒤 split을 할 필요가 있었다.
str = str.trim(); // 추가된 코드
String[] arr = str.split(" ");
System.out.print(arr.length);
trim() 메소드를 추가하여 다시 제출했더니 이번에도 실패였다.
이번엔 무엇이 문제인고 보니 테스트 케이스로 공백만 있는 입력이 들어왔을 때가 문제였다.
(공백)
결과 : 1
입력으로 공백이 들어오면 trim() 메소드가 잘라내버려 str = ""
상태가 된다.
그럼 str 안에는 " ", 즉 공백이 존재하지 않으므로 split의 regex인 " "가 발동되지 않아 split()으로 쪼개지지 않는다.
결국 arr 안에 들어가 있는 건
[0] : ""
인 것이다.
여기서 생기는 한 가지 의문.
"" == null
이라면, arr의 사이즈는 0이 되어야 맞지 않나?
왜 결과값이 1이 나온 거지?
그렇다면 "" != null
이라는 얘기인가?
*(참고 링크 < 해당 정보는 이 링크에서 발췌한 것입니다.)
결론부터 말하면 둘은 같지 않다.
null
은 변수는 있지만, 어떤 객체를 가리키는 대상이 없는 경우이다.
반면에 빈 문자열은 문자열 객체(인스턴스)가 실제로 있으며, 그 내용이 ""
인 경우를 말한다.
문자열 변수로 선언된 null 변수 nullString이 있다고 생각해 봅시다.
nullString에 대하여는 아래처럼 동작한다.
System.out.println(null == nullString); // true
System.out.println(nullString.equals("")); // NullPointerException 발생!!
null이 아닌 빈 문자열 emptyString이 있다고 생각해보자.
emptyString에 대하여는 아래처럼 동작한다.
System.out.println(null == emptyString); // false
System.out.println(emptyString.equals("")); // true, 에러 발생 안함.
null은 객체를 가리키고 있지 않은 상태이고, 빈 문자열은 객체가 있지만 내용이 ""
인 상태인 것이다.
둘은 서로 같지 않다.