12345

C언어에서 문자열을 생성하고 싶을때, 힘들게 작성하던 기억이 가물가물 거립니다.
C언어에서 새롭게 자바를 배울때 너무 간단히 문자열을 생성할수 있는 것을 보고 신기했던 기억이 나네요.

자바를 공부하시는 분들은 알겠지만 String 클래스를 이용하여 문자열을 생성하는 방법은 크게 2가지로 나뉘고 있습니다.
예를들어, a라는 String(이하 스트링) 객체에 abc라는 문자열을 삽입할때를 보면,

 1. String a = "abc"
 2. String a = new String("abc");

이렇게 2가지 방법이 존재하지요.

막상 1번과 같이 생성한다고 해도, 자바 내부에서는 2번과 같이 변환된다고 대학교 2학년 자바시간때 교수님이 말씀하시던게
생각납니다.

하지만 과연 위의 1,2번이 같을까요?

단순하게 스트링 객체 2개를 비교하는 방법으로 부터 시작해보겠습니다.

문자열을 비교할때 어떤 방법을 사용하시나요?

이전에 C언어를 하신분이나, 자바 기본서를 조금 읽어보신 분은 ==  비교연산자를 이용할거라 생각하실수도 있습니다.

== 을 이용해 볼까요?


위와 같이 리터럴을 지정하는 유형으로 했을때, 같다고 출력하네요..^^;
그럼 이번엔 스트링 클래스의 생성자를 이용했을시도 과연 같은 결과가 출력될까요?



어..? 이번에는 같다고 안나옵니다 -_-;

그럼 결론이 스트링을 사용할시, 리터럴과 생성자의 차이점이 존재하는거 같아요.

그런데 그전에 스트링 생성자를 이용할시 문자열이 같을시에 같게 하려면 어떻게 할까요?

답은 String 클래스의 equals 메소드를 이용하시면 됩니다..^^




이제는 같다고 출력되는걸 볼수가 있네요~ JAVA API에서 String 클래스의 equals 메소드의 사용법은 아래와 같이 나와있습니다.

Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.

앞에서 봤던 리터럴 지정 유형으로 equals 메소드로 비교 해볼까요?



문제없이 같다고 나오고 있습니다..^^


그럼 이제 본격적으로 왜 2가지 방식의 차이가 존재할까요?

간단히 말해서 JVM 에서는 리터럴로 문자열을 생성할 경우, 같은 내용의 문자열은 하나의 스트링 인스턴스를 참조하도록
되어 있습니다. 즉, String a = "abc"; 을 이용하여 스트링 인스턴스를 생성하고, 그 뒤에 String b = "abc"; 가 오면,
JVM에서는 이전에 생성된 스트링 인스턴스와 문자열과 새로운 문자열을 비교합니다. 

이때 문자열이 서로 같을시에는 b 인스턴스를 생성하는것이 아닌, b의 레퍼런스 변수가 a 인스턴스를 참조하도록 해주는 것이지요.^^

따라서, 결론적으로 리터럴를 이용한 스트링 생성시에는 문자열이 같을 경우에는 하나의 스트링 인스턴스를 여러 레퍼런스
변수가
참조한다. 라고 생각할수 있겠습니다..^^

정확히 말하면, 최초 문자열 생성시에, 문자열을 constant pool(상수풀)에 보관을 합니다. 이 상수풀에 보관된 문자열을
다음에 스트링 인스턴스를 생성하기 전에 JVM에서 비교해 주는 것이지요~

여기서 중요한건 생성자를 이용하여 생성할시에는 constant pool에 보관을 안하고, 리터럴을 이용하여 스트링 생성시에
constant pool에 보관되는 효과를 보여준다는 점입니다..

따라서, == 비교 연산자를 이용한 연산결과의 출력도 이제 이해가 갈텐데요.
레퍼런스 변수가 같은 인스턴스의 주소를 가지고 있기때문에 서로 같다고 출력이 되는 것입니다~

하지만, 생성자 를 이용하여 문자열을 생성시에는, 위와 같은 과정들을 하지 않습니다.
문자열이 같아도 그냥 단순히 문자열 인스턴스를 계속 생성하고, 레퍼런스 변수가 각각의 인스턴스를 참조할 뿐이지요..^^
따라서, == 비교 연산자의 출력도 같이 않기 때문에 false 로 출력될수밖에 없습니다.

하지만, String 클래스에서 제공하는 equals 메소드는 문자열 자체를 비교하는 것이기 때문에 위의 스트링을 생성하는 것과 무관하게,
올바른 결과값을 보여줍니다..^^

그럼 생성자를 이용한 스트링 인스턴스를 리터럴로 생성된것과 같은 효과를 낼수는 없을까요?
답은 String 클래스의 intern() 메소드입니다.

JAVA API에서 intern() 메소드의 사용법은 아래와 같이 나와 있습니다.

Returns a canonical representation for the string object.

A pool of strings, initially empty, is maintained privately by the class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t)
is true.


간단히, intern() 메소드는 해당 스트링이 constant pool(상수풀)에 등록된 스트링일 경우에는, 그 스트링의 주소값을 반환합니다.
즉, 생성자를 이용해 생성한  스트링의 레퍼런스 변수가 상수풀에 등록된 스트링을 참조하게 됩니다.
이전에 따로 생성된 인스턴스는 JVM의 가비지컬렉터에 의하여 사라지겠지요..

아래와 같은 예제를 실행해보시면 알것 같습니다..^^



intern() 메소드 실행후에 == 비교연산자가 true로 반환되는 것을 알수가 있네요..^^

이제 어느정도 String 클래스를 이용한 문자열 생성법의 2가지 차이에 대해 이해가 되셨으면 좋겠습니다..!


tagged with  IT, java, string, 자바, 대한민국>서울
TRACKBACK ADDRESS : http://josuae.tistory.com/trackback/149 관련글 쓰기
이름 :
비밀번호 :
홈사이트 :
비밀글 :

예전부터 자바 공부를 하면서 궁금했던 사항입니다.

BufferedReader 클래스와 Scanner 클래스의 차이는 무엇일까요?

우선 네이버 검색을 시도해봤는데, 딱히 적당한 결과를 찾지도 못했습니다.

우리의 구글링으로 검색한 결과, Sun사의 JAVA 포럼에서 비슷한 질문이 올라온거 같네요..^^
(http://forums.sun.com/thread.jspa?threadID=773648&tstart=35835)

결론적으로 Scanner 클래스는 JDK 1.5 버젼부터 등장한 클래스고, 초보자들이 쓰기는 쉬운거 같은데, 아래와 같이 메세지를 주시네요.

The Scanner should not be used for simple input for beginner's programs.


아래와 같은 메세지도 존재하네요..^^

Scanner seems like such a simple, but Swiss-Army-Knife kind of tokenizer (it does all sorts of things, without regard to any particular context) that it seems like it was introduced specifically for newbies or for people who want to write some quick-and-dirty code. I would think that if you were doing any really advanced stuff you'd write a specialized parser or use whatever the java equivalent of lex is.


하지만 정확히도 저도 자세히는 잘 모르겠네요..

코드 간결도에 있어서는 BufferedReader가 Scanner보단 더 나을거 같기도 하지만, 속도면에서는 BufferedReader가 나은것
같습니다만, 2개중에 무엇을 더 하는게 좋을거 같은지는 조금 더 찾아봐야 할거 같습니다.. ㅠㅠ



tagged with  java, 자바, 프로그래밍
TRACKBACK ADDRESS : http://josuae.tistory.com/trackback/148 관련글 쓰기
이름 :
비밀번호 :
홈사이트 :
비밀글 :
*1 
ㅠㅠ
알립니다
episode
activity
blog
everyday
programming
portfolio
seminar
thinking
nonclassified
secret scrap
ipod touch
count total 68,944, today 3, yesterday 10