2011-04-29 7 views
16

다음 Java 코드 세그먼트는 AP 컴퓨터 과학 실습 시험에서 나왔습니다.Java 문자열 변수 설정 - 참조 또는 값?

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2); 

이 코드의 출력은 BlueJ에서 "abc ab"입니다. 그러나 가능한 대답 선택 중 하나는 "abc abc"입니다. 그 대답은 Java가 문자열 참조를 원시 타입 (값에 따라)으로 설정하는지 또는 객체 (참조로)와 같이 설정하는지에 따라 달라질 수 있습니다.

int s1 = 1; 
int s2 = s1; // copies value, not reference 
s1 = 42; 

System.out.println(s1 + " " + s2); // prints "1 42" 

을하지만, 우리가 균형을 잡고는 BankAccount 객체했다 말 :

더이 문제를 설명하기 위해 원시 유형의 예를 살펴 보자.

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1.setBalance(0); 
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 0" 

문자열에 어떤 것이 있는지 확실하지 않습니다. 그것들은 기술적으로 객체이지만, 컴파일러는 변수를 서로 설정할 때 원시 타입처럼 취급합니다.

자바가 원시 변수처럼 문자열 변수를 전달하면 대답은 "abc ab"입니다. 그러나 Java가 문자열 변수를 다른 객체에 대한 참조와 같이 취급하는 경우 대답은 "abc abc"가됩니다.

어느 정답으로 생각하십니까?

+0

문자열에 대한 설명서를 보았습니까? 그것이 클래스인지 또는 원시인지 여부를 말합니까? – DJClayworth

+0

질문에 대한 답변을 얻으려면 [javadoc] (http://download.oracle.com/javase/6/docs/api/java/lang/String.html)을 읽어보십시오. –

+4

'System.out.println (s1 + ""+ s2); // prints "1 42"'사실이 아니다. 그것은 출력한다. ""42 1 "' – whytheq

답변

27

java 문자열은 변경할 수 없으므로 재 할당으로 인해 실제로 String 값을 변경하지 않고 변수가 새 String 인스턴스를 가리 키도록합니다.

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2); 

, 2 행, s1 == s2 및 s1.equals (s2). 3 행에서 연결 한 후 s1은 이제 "abc"의 불변 값을 가진 다른 인스턴스를 참조하므로 s1 == s2도 s1.equals (s2)도 아닙니다.

+1

그것은 그렇습니다.하지만 실제로 OP의 근본적인 질문에는 답하지 않습니다. –

+5

물론 가능합니다. 문자열 케이스와 BankAccount의 비교가 동일하지 않음을 암시 적으로 설명합니다. 하나는 새 인스턴스를 할당하는 반면 다른 하나는 기존 인스턴스를 수정하는 것입니다. 명확성을 위해 s1 = s1 + "c"는 기본적으로 b = new StringBuilder (s1)과 같습니다 .b.append ('c'); s1 = b.toString(); – Robin

2

java.lang.String은 원시 객체가 아니라 객체입니다. 코드가 첫 번째 예에서 무슨 짓을

은 다음과 같습니다

  1. "AB"
  2. 설정 S2 동일한 기본 개체와 같은지 (S1) 등으로 (S1)을 정의
  3. 설정 S1 새 문자열과 동일 그 s1의 이전 값과 "c"의 조합입니다.

그러나 참조 또는 값에 대한 질문에 대한 대답은 참조 용입니다.

6

Java에서 String 개체는 주위에 할당되고 전달됩니다 (참조 :). 이 점에서 그들은 다른 어떤 대상과 똑같이 행동합니다.

그러나 String입니다. : 새 개체를 만들지 않고 기존 문자열의 값을 수정하는 작업이 없습니다. 예를 들어 s1 = s1 + "c"은 새 개체를 만들고 s1에 저장된 참조를이 새 개체에 대한 참조로 바꿉니다.

9

문자열이 프리미티브처럼 처리되는지, 객체처럼 처리되는지는 관련이 없습니다!

문자열 예제에서 두 문자열을 연결하면 새 문자열 인스턴스이 생성되고 s1에 할당됩니다. 변수 s2는 여전히 변경되지 않은 (!) 이전 String 인스턴스를 참조합니다. 는 BankAccount 가정

새로운는 BankAccount를 반환 균형을 설정하는 방법을했다, 당신의 예는 다음과 같이 수 :

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1 = b1.createNewAccountWithBalance(0); // create and reference a new object 
System.out.println(b1.getBalance() + " " + b2.getBalance()); // prints "0 500" 
13

귀하는 BankAccount와 문자열 사이의 차이는 문자열 불변 것입니다. 'setValue()'또는 'setContent()'와 같은 것은 없습니다. 은행 계좌와 동등한 예는 다음과 같습니다 당신이 그것을 이런 식으로 생각한다면

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1 = new BankAccount(0); 
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 500" 

(실제로 컴파일러는 무엇을하지만, 기능적으로 동등한) 문자열 연결 시나리오는 다음과 같습니다

String s1 = "ab"; 
String s2 = s1; 
s1 = new String("abc"); 
System.out.println(s1 + " " + s2); //prints "abc ab" 
9

실제로 String은 클래스이며 참조로 지정되거나 전달됩니다. 은 그러나 혼란은 성명 :

String s = "abc"; 

문자열이 primitve가 ('int x = 10;를'같은) 것을 제안한다; 하지만 그것은 바로 가기입니다. 'String s = "abc";' 실제로 그냥 'Integer x = 10;'와 같은 'String s = new String("abc");' 로 컴파일이 메커니즘은 '복싱'이라고 'Integer x = new Integer(10);'

로 컴파일됩니다. 클래스 'Integer'와 원시적 'int', 거기하지만 (char[] 가까이 온다 allthough) 문자열

Sije 드 하안

0
int s1 = 1; 
int s2 = s1; // copies value, not reference 
s1 = 42; 

System.out.println(s1 + " " + s2); // prints "1 42" 
원시적 해당이되지 않습니다

그리고 더 혼란이다

"1 42"을 인쇄하지 않고 "42 1"을 인쇄하지 않습니다. 각 개별 선을 고려하십시오. 첫 번째 s1이 1을 지정한 다음 s2가 s1을 할당합니다 (지금까지는 Java가 세 번째 행을 보지 못했다고 가정). 세 번째 라인과 즉시 c 그 java가 지금까지 알고있는 것을 인쇄하라는 말을 듣고, s1은 42이고 s2는 1 (오래된 s1)입니다.

문자열의 경우에도 동일한 문제가 발생합니다.

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2);// prints "abc ab". 

포트 문자열은 반드시 S1 변경 않지만 오히려 지금은 힙 메모리에 새로운 String 객체를 참조 S1하지만 이전 "AB"개체는 S2의 새로운 참조하여, 아직 거기!

0

자바가 다른 객체에 대한 참조와 같은 문자열 변수를 처리하는 경우 주장은, 대답은 "ABC ABC"

가 잘못된 것입니다. Java는 String 변수를 다른 Object에 대한 참조와 같이 취급합니다. Strings은 Objects이지만 대답은 "abc ab"입니다.

문제는 할당 연산자가하는 것이 아닙니다. 할당 연산자는 모든 경우에 String 객체에 대한 참조를 할당합니다.

문제는 연결 연산자 ('+')가하는 것입니다. 새 String 객체를 만듭니다. 다른 말했듯이, 이것은 String 객체가 변경 불가능하기 때문에 필요합니다. 그러나 그것은 String이 변경 불가능하기 때문에뿐만 아니라 연산자 동작의 문제입니다. 연결 연산자는 String 객체가 변경 가능하더라도 새 Object를 반환 할 수 있습니다.

대조적으로, 두 번째 예제에서 b1.setBalance (0)은 새 개체를 만들지 않고 기존 개체를 수정합니다.

관련 문제