1、问题描述
java方法传String类型的参数时,为啥方法对值的修改没有在方法之外生效?假设是其他类型的对象,那么方法对对象的数据的修改是会在方法之外生效的啊,可是String类型也是对象类型啊,为啥就没有在方法之外生效呢?
2、代码示例
//示例1:对象类型
public class PassReferByValue
{
String a = "123";
public static void test(PassReferByValue test)
{
test.a = "abc";
}
public static void main(String[] args)
{
PassReferByValue test = new PassReferByValue();
System.out.println("对象的数据的初始值是:" + test.a); //123
test(test);
System.out.println("通过调用test方法修改对象的数据的值之后:" + test.a); //abc
}
}
总结:因为是对象类型,所以方法每次修改对象的数据的值之后,都在方法之外生效了,也就是说,在方法之外和在方法之内访问到的对象的数据的值是一致的。
//示例2:String类型
public class Test
{
public static void test(String str)
{
str = "word";
}
public static void main(String[] args)
{
String string = "hello";
System.out.println("对象的数据的初始值是:" + string); //hello
test(string);
System.out.println("通过调用test方法修改对象的值之后还是以前的值:" + string); //hello
}
}
总结:如果方法的参数是String类型,虽然方法修改了它的值,但是并没有在方法之外生效,也就是说,在方法之外和在方法之内的访问到的值不一样!!!这是为什么???
3、网上的解释
String等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待。
http://blog.csdn.net/fbysss/article/details/3082949
这样的解释太肤浅了,完全是基于文字的描述,有没有基于代码层面的解释,或者其他的更深层次的解释呢?
阿神2017-04-18 09:15:32
이해하신 대로
예시 1은 참입니다对象的数据的修改
, 예 2는 참입니다参数本身的修改
값으로 전달하든 참조로 전달하든 본질적으로 值传递
과 동일합니다. 메소드가 호출되면 매개변수의 값이 계산되어 해당 매개변수에 복사본이 제공됩니다
객체 유형에 한해 객체의 참조(또는 포인터, 주소로 이해됨) 값이 전달되지만 매개변수는 복사된 참조를 가져오지만 원래 참조와 동일한 객체를 가리키므로 이 참조에 따르면 원본 객체의 데이터를 조작할 수 있습니다
두 번째 예에서는 메소드를 호출할 때 string
매개변수의 값(메모리에 있는 문자열 객체 hello
의 주소로 이해될 수 있음)을 계산하고 이를 str
매개변수에 복사합니다. str
원래 hello
문자열 객체에 대한 참조를 얻었지만(즉, str
의 값은 string
의 값, 즉 hello
의 주소와 같습니다) 즉시 이 매개변수를 다시 할당했습니다. . 이때 str
매개변수 뒤에 hello
문자열이 왔는데, str
는 더 이상 hello
을 가리키지 않고 대신 world
을 가리킵니다. hello
자체와 메모리에 있는 hello
의 주소는 메서드 외부에서 전혀 변경되지 않습니다. string
변수는 항상 hello
문자열 개체를 가리켰습니다.
天蓬老师2017-04-18 09:15:32
세 문장으로 요약하자면:
1. 对象
은 传引用
2. 原始类型
은 传值
입니다. 3. self-를 제공하지 않습니다. 수정 함수, 각 작업은 새로운 개체를 생성하므로 특별하게 처리해야 합니다. 값을 전달하는 것으로 간주될 수 있습니다. String,Integer, Double
정수는 문자열과 동일합니다. 값을 보유하는 클래스 변수는 Final 속성이며 수정할 수 없으며 새 개체를 다시 할당하거나 생성할 수만 있습니다. Integer가 메서드 매개 변수로 메서드에 전달되면 이를 할당하면 원래 Integer의 참조가 메서드 내의 스택 주소를 가리키게 되어 원래 클래스 변수 주소에 대한 포인터가 손실됩니다. 할당된 Integer 객체에 수행된 모든 작업은 원본 객체에 영향을 주지 않습니다.
링크 설명
PHPz2017-04-18 09:15:32
test1.a = "567"
여기서 변경하는 것은 test1
에서 참조하는 객체의
str = "word"
여기서 변경하는 것은 참조변수 str
가 가리키는 객체입니다.
간단히 말하면 샤오밍과 샤오홍 두가지가 있는데 샤오밍 손을 로봇손으로 바꾸면 진짜 샤오밍 손이 바뀌는데 샤오홍 이름을 샤오밍으로 바꾸면... 샤오홍 자신은 여전히 변하지 않았습니다.
디퍼, 샤오밍, 샤오홍이 이벤트에 참여할 예정입니다. 본 이벤트는 실명을 알 필요가 없으므로 코드네임 A, B가 부여됩니다. 이때 A씨는 활동 중 부상을 입어 손잡이가 기계식 손잡이로 교체됐다. 그 결과 활동 후 샤오밍의 손은 실제로 기계식 손잡이로 교체됐다. 그런데 B는 이름표를 C로 바꿨을 뿐입니다. 나온 후에도 샤오홍은 여전히 샤오홍이고 C에 해당하는 사람이 되지 않았습니다.
여기서 활동은 메소드이고 할당된 코드는 형식 매개변수입니다. 형식 매개변수에 직접 할당하면 실제 매개변수에 영향을 미치지 않지만 형식 매개변수가 참조하는 개체의 속성에 값을 할당하면 실제로는 개체의 속성에 영향을 미칩니다.
이해에 도움이 될 수 있도록 주석과 함께 코드를 추가하겠습니다. 메소드 호출의 실제 프로세스에는 스택과 같은 지식도 포함된다는 것을 이해하고 싶다면 그렇게 복잡하지 않습니다. 이 코드에는 출력이 없습니다. 이해한 후 일부 출력을 추가하여 이해가 올바른지 확인할 수 있습니다.
으아악阿神2017-04-18 09:15:32
문자열은 불변 유형입니다. 즉, 해당 값이 불변임을 의미합니다. 예를 들어 String a = "abc"
에서는 메모리에서 참조 a가 메모리 블록 "abc"를 가리킨다. a = "bcd"
을 사용하면 "abc"가 위치한 메모리 블록의 값이 "bcd"로 변경되지 않는다. 또 다른 문자열 "bcd"가 생성된 다음 a가 "bcd"를 가리키므로 메서드 외부의 참조는 여전히 "abc"의 메모리를 가리킵니다.
변수 유형은 "abc"가 있는 메모리의 값을 직접 수정합니다. 이런 방식으로 메서드 외부의 참조는 여전히 원래 메모리 주소를 가리키므로 메서드 외부에서 수정된 값에 액세스할 수 있습니다.
阿神2017-04-18 09:15:32
String 개체에 포함된 문자열은 수정할 수 없습니다. String 유형 변수를 다시 할당하면 해당 참조도 변경되어 새 개체가 됩니다.