2009-02-09 2 views
2

Concat()은 원래 값을 수정하지 않습니다. 새 값을 반환합니다. 이 같은
:Java의 일부 메소드가 원래 값을 수정하는 이유는 무엇입니까?

String str = "good"; 
str.concat("ness"); 
System.out.println(str); //"good" 

그러나 일부 방법은 원래의 값을 수정합니다. 왜? 그루비에서

:

def languages = ["Java", "Groovy", "JRuby"] 
languages.reverse() 
===> [JRuby, Groovy, Java] 
println languages 
===> [Java, Groovy, JRuby] 


languages.sort() 
===> [Groovy, JRuby, Java] 
println languages 
===> [Groovy, JRuby, Java] 
+0

예제는 잘 선택되지 않았습니다. 입력 문자열을 수정하는 방법은 어디입니까? 여러분이 말하는 것처럼, collect는 입력을 수정하지 않지만 println은 입력을 수정하지 않습니다. – Frank

+0

편집 후 : Groovy 예제가 요점을 설명합니다. 나는 이제 그 문제를 이해한다. – Frank

답변

11

String는 자바에서 변경할 수 없습니다.String을 "수정하는"모든 메서드는 String의 새 인스턴스를 반환해야합니다. Java API Specifications for the String class 가입일

:

문자열 상수이고; 을 만든 후에는 해당 값 을 변경할 수 없습니다.

The Java Language SpecificationsSection 4.3.3: The Class String에이 동작을 정의합니다. 편집에


응답 :

는 그루비의 예가 추가 된 것으로 보인다. (내가 전에 그루비를 사용하지 않은, 그래서 그것의 나의 이해는 정확하지 않을 수 있습니다.) 나는 예보고에서 이해하는 것과

는 -ed reversesort을하고있는 languages 목록이 될 것 같다 - ed - 해당 작업 자체가 목록에 포함 된 String 개 객체를 수정하지 않지만 목록 자체에서 작동합니다.

목록에서 새 목록을 반환하는 방법 또는 목록을 수정하거나 수정하지 않는 방법은 String 개체 자체의 동작과 관련이 없습니다.

+0

아니요, 그루비 예제의 요점은 reverse() 메서드가 객체를 수정하지 않고 대신 새 객체를 반환한다는 것입니다. 반면 sort()는이를 수정합니다. – Frank

+0

@dehmann : 아, 그 부분을 놓쳤습니다! 그 점을 지적 해 주셔서 감사합니다! – coobird

+0

@dehmann : 왜 reverse() 메서드는 새 객체를 반환하고 sort()가 그것을 수정합니까? API가 표시되지 않으면 어떤 규칙이 적용될 수 있습니까? – JSON

0

변경 가능하고 변경할 수있는 클래스가 있기 때문입니다.

String 다른 대답이 지적한대로, 불변 클래스입니다. 문자열이 생성되면 값은 항상 동일하게 유지됩니다.

ArrayList<Integer> 개체가있는 경우 해당 add 함수를 사용하여 다른 정수를 목록에 추가 할 수 있습니다. add 함수는 새 목록을 반환하는 대신 현재 위치에서 목록을 변경합니다. ArrayList는 변경 가능합니다.을 편집 할 수

응답 : 그루비 예를 들어

은, 아마 그 디자이너는 앉아서 더 자주 하나는 반대 결과가 포함 된 새 목록을 원하고 훼손되지 않은 기존의 목록을 유지하는 것으로 나타났습니다. (왜? 몰라). 다른면에서, 그들은 정렬 된 결과를 포함하는 새 목록을 원하지 않는 경우가 더 많다는 것을 알았을 수도 있습니다. 그래서 그 자리에서 그 일을합니다. 그러나 나는 잘 모르며 전에 그루비를 사용하지 않았다. 그래서 추측한다.

newObj = obj.sort(); // new sorted list is returned 
obj.sort!(); // obj is sorted in-place 
: 새로운 오브젝트가 느낌표 표시가없는 한 그 결과를 돌려 그 후 서면 감탄이 자리에서 오브젝트를 변경 기능, 함수 :

루비, 나는 이것에 대한 개념이 들었습니다

3

자바 API는 많은 사람들이 디자인했기 때문에 모든 것을 일관성있게 유지하기가 어렵습니다. 저는 사람들이 일반적으로 값의 대상이 걱정되는 곳에서는 불변성 (즉, 내부 상태가 변경되어서는 안됨)이 현재 좋은 것으로 받아 들여지고 있다고 생각합니다.

또 다른 유사한 질문은 "인덱스가 때로는 0 기반 (대부분의 경우)이고 일부는 1 기반 (JDBC) 일 때"입니다. 다시 말하지만, API의 또 다른 상황이 너무 광범위하고 조정되지 않는 다른 API 개발자가 있다고 생각합니다. JDBC가 1 기반 인 실제 이유를 알고 있다면 알려 주시기 바랍니다.

+0

JDBC가 1 기반 인 것은 실제로 예외이며 표준은 0 기반입니다. 어쩌면 일부 데이터베이스 API가 표시 될 수 있습니다. – starblue

2

대신 str.concat("ness")이라고 생각합니다. 이 특정 예제에서 String s는 String불변이되도록 설계되었으므로 해당 방법으로 개체를 변경할 수 없습니다. 라이브러리에서 객체의 상태를 변경하는 많은 메소드 (예 : StringBuffer.replace())와 그렇지 않은 메소드 (예 : String.replace())를 찾을 수 있습니다. 어떤 경우인지 판단하기 위해 신중하게 API을 읽어야합니다. 궁극적으로이 기능은 라이브러리 디자이너가 선택한 기능으로 사용하기 쉽고 작성한 패키지와 관련된 규칙을 고려해야합니다.

+0

다음과 같은 규정이 있다면 좋지 않겠습니까? 메서드가 개체의 내부에 대한 액세스가 필요없고 개체의 상태가 변경되지 않으면 메서드가 멤버가 아니어야합니다 (또는 정적이어야합니다). String.replace()가 좋은 예입니다. – Frank

+0

나는 동의한다. 확실히 API를보다 일관되게 만들 수 있습니다. –

0

이것은 어느 정도 프로그래밍 스타일과 관련이 있습니다. 원래 개체를 변경하지 않고 변경 내용을 반영하기 위해 새 복사본을 만드는 것은 안전한 프로그래밍을위한 관용구입니다. Josh Bloch가 그의 책 "Effective Java"(제 1 판)에서 언급 한 것 같습니다. 그가 그것을 위해 사용한 정확한 용어를 기억할 수는 없지만.

문자열의 경우 String은 변경 불가능하므로 새 객체를 반환합니다. 그러나 Java API 전체에서 원래 개체가 변경된 곳과 새 개체가 반환되는 곳이 표시됩니다. 누군가 다른 사람이 앞서 지적했듯이, 다른 사람들이 API에 대해 연구하고 자신의 프로그래밍 스타일을 가져 왔기 때문입니다.

약간 다른 메모 : 개체를 변경할 수 없게 유지하면 코드에 안전성이 추가되고 특정 방식으로 코드를 작성할 수 있습니다. 날짜의 모든 방법은 자신의 상태의 변화하는 대신 새로운 객체를 반환하는 경우

(new Date()).add(new Month(7)).add(new Day(4))

는, 우리는 같은 코드를 작성할 수 있습니다. 이것은 프로그램을 매우 가독성있게 만든다.

그러나 개체를 변경하지 않으면 개체가 많은 경우 시스템 성능이 저하 될 수 있습니다.

관련 문제