java 方法 入?yún)⒌膮?shù)的值,如果在方法體對(duì)參數(shù)進(jìn)行修改,則 基本類(lèi)型值不變窗悯,需要return 返回值;而引用類(lèi)型如果不修改原指針時(shí)賦值將改變偷拔;
其中基本數(shù)據(jù)類(lèi)型包含 8大基本類(lèi)型 和 String
怎么理解而引用類(lèi)型如果不修改原指針時(shí)賦值將改變:
如果 setVale(List list) 中 list集合蒋院,如果 對(duì) list 集合重新賦予地址 eg. 方法體{ list=new list()},此時(shí)原值不變亏钩;如果對(duì)list 集合里面的數(shù)據(jù)賦值,則值會(huì)改變 . eg.方法體 {list.add(a)},打印list 值會(huì)改變;
思考原因:
因?yàn)?方法體 會(huì)建立臨時(shí)表(局部變量表)會(huì)建立新的堆棧悦污,對(duì)直接 的引用 不處理铸屉,所以 8大基本類(lèi)型和string 還有 引用類(lèi)型,直接處理不改變其值切端;但是 臨時(shí)表 會(huì) 拿到 引用類(lèi)型的指針彻坛,對(duì)指針的值重新賦值是可以的,所以 可以改變 list 集合里面的數(shù)據(jù)踏枣。
public static void main(String[] args) {
String S="ASDFASDF";
setValue(S);
System.out.println(S);
int i=466546;
setValueInt(i);
System.out.println(i);
//發(fā)現(xiàn) 基本數(shù)據(jù)類(lèi)型 和 String 經(jīng)過(guò)方法處理后 值不變化 String本質(zhì)是final類(lèi)型char數(shù)組
// 而數(shù)組 和 list 集合 經(jīng)過(guò) 方法處理后 期 里面的值會(huì)發(fā)生變化
//說(shuō)明 基本數(shù)據(jù)類(lèi)型 和String 是值拷貝昌屉,而 數(shù)組和list 集合處理的是引用
StringBuilder str = new StringBuilder("546");
setValue(str);
System.out.println(str.toString()); //輸出空字符串
setValue2(str);
System.out.println(str.toString()); //輸出sss
}
public static void setValue(StringBuilder str){
str = new StringBuilder("sss111");
}
public static void setValue2(StringBuilder str){
str.append("sss222");
}
public static void setValue(String ss){
ss="adfasdfa";
}
public static void setValueInt(int ss){
ss=8888;
}
參考:
Java 變量參數(shù)傳入方法,修改后是否影響外面的值
public class Test2 {
public static void setValue(String str){
str = "ss";
}
public static void setValue(Man str){
str = new Man("test");
}
public static class Man{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Man(String name) {
this.name = name;
}
@Override
public String toString() {
return "Man{" +
"name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) {
String str = "s";
setValue(str);
System.out.println(str);
Man man = null;
setValue(man);
System.out.println(man);
}
}
如上面代碼實(shí)踐茵瀑,結(jié)果輸出
s
null
原因是方法在執(zhí)行的時(shí)候有棧幀的概念间驮,入棧的時(shí)候只是壓棧方法參數(shù)是傳入?yún)?shù)的副本。
JVM高級(jí)特性
此時(shí)區(qū)分?jǐn)?shù)據(jù)類(lèi)型:基本類(lèi)型和引用類(lèi)型
基本類(lèi)型:值存放在局部變量表中马昨,無(wú)論如何修改只會(huì)修改當(dāng)前棧幀的值竞帽,方法執(zhí)行結(jié)束對(duì)方法外不會(huì)做任何改變;此時(shí)需要改變外層的變量鸿捧,必須返回主動(dòng)賦值屹篓。
引用數(shù)據(jù)類(lèi)型:指針存放在局部變量表中,調(diào)用方法的時(shí)候匙奴,副本引用壓棧堆巧,賦值僅改變副本的引用。但是如果直接改變副本引用的值泼菌,修改了引用地址的對(duì)象谍肤,此時(shí)方法以外的引用此地址對(duì)象當(dāng)然被修改。(兩個(gè)引用哗伯,同一個(gè)地址荒揣,任何修改行為2個(gè)引用同時(shí)生效)
比如
public static void setValue(StringBuilder str){
str = new StringBuilder("sss");
}
public static void setValue2(StringBuilder str){
str.append("sss");
}
public static void main(String[] args) {
StringBuilder str = new StringBuilder();
setValue(str);
System.out.println(str.toString()); //輸出空字符串
setValue2(str);
System.out.println(str.toString()); //輸出sss
}
關(guān)于String,本質(zhì)是final類(lèi)型char數(shù)組焊刹,不可修改系任,只能賦值,在做參數(shù)傳入方法修改時(shí)伴澄,其實(shí)是新建對(duì)象赋除,必須返回重新對(duì)外面的變量賦值才會(huì)對(duì)外面的String引用生效。
看String源碼的任意一個(gè)方法即可明白
/**
* Returns a string resulting from replacing all occurrences of
* {@code oldChar} in this string with {@code newChar}.
* <p>
* If the character {@code oldChar} does not occur in the
* character sequence represented by this {@code String} object,
* then a reference to this {@code String} object is returned.
* Otherwise, a {@code String} object is returned that
* represents a character sequence identical to the character sequence
* represented by this {@code String} object, except that every
* occurrence of {@code oldChar} is replaced by an occurrence
* of {@code newChar}.
* <p>
* Examples:
* <blockquote><pre>
* "mesquite in your cellar".replace('e', 'o')
* returns "mosquito in your collar"
* "the war of baronets".replace('r', 'y')
* returns "the way of bayonets"
* "sparring with a purple porpoise".replace('p', 't')
* returns "starring with a turtle tortoise"
* "JonL".replace('q', 'x') returns "JonL" (no change)
* </pre></blockquote>
*
* @param oldChar the old character.
* @param newChar the new character.
* @return a string derived from this string by replacing every
* occurrence of {@code oldChar} with {@code newChar}.
*/
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */
while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
//String的value 是final char[]非凌,一旦創(chuàng)建不能改變
return new String(buf, true);
}
}
return this;
}
引用類(lèi)型會(huì)引起淺拷貝和深拷貝現(xiàn)象举农。