java方法传String类型的参数时,为啥方法对值的修改没有在方法之外生效?
巴扎黑
巴扎黑 2017-04-18 09:13:32
0
8
1056

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

这样的解释太肤浅了,完全是基于文字的描述,有没有基于代码层面的解释,或者其他的更深层次的解释呢?

巴扎黑
巴扎黑

membalas semua(8)
阿神

Mengikut pemahaman anda

Contoh 1 memang benar 对象的数据的修改, tetapi contoh 2 adalah benar 参数本身的修改

Sama ada ia melalui nilai atau lulus melalui rujukan, ia pada asasnya sama dengan 值传递 Apabila kaedah dipanggil, nilai parameter dikira dan salinan diberikan kepada parameter yang sepadan

.

Hanya untuk jenis objek, nilai rujukan (atau difahami sebagai penunjuk, alamat) objek dihantar Walaupun parameter mendapat rujukan yang disalin, ia menunjuk ke objek yang sama dengan rujukan asal, jadi menurut rujukan ini, anda boleh Mengendalikan data objek asal

Dalam contoh kedua anda, apabila memanggil kaedah, hitung nilai parameter string (yang boleh difahami sebagai alamat objek rentetan hello dalam ingatan) dan salin ke parameter str, walaupun parameter str Mendapat rujukan kepada objek rentetan hello asal (iaitu, nilai str adalah sama dengan nilai string, iaitu alamat hello), tetapi serta-merta menetapkan semula parameter ini. Pada masa ini, parameter str telah diikuti oleh rentetan hello tiada kaitan antara satu sama lain str tidak lagi menunjuk ke hello, tetapi sebaliknya, dalam proses ini, alamat world itu sendiri dan hello dalam ingatan tidak berubah sama sekali, di luar kaedah Pembolehubah hello sentiasa menunjuk ke objek rentetan string tanpa sebarang perubahan hello.

Peter_Zhu

Untuk meringkaskan dalam tiga ayat:
1 对象 ialah 传引用
2 原始类型 ialah 传值
3. Fungsi pengubahsuaian, setiap operasi menjana objek baru, jadi ia mesti dirawat secara khusus. Ia boleh dianggap sebagai lulus mengikut nilai. String,Integer, DoubleInteger adalah sama dengan String. Pembolehubah kelas yang memegang nilai ialah sifat Akhir dan tidak boleh diubah suai Ia hanya boleh ditugaskan semula/menjana objek baharu. Apabila Integer dihantar ke dalam kaedah sebagai parameter kaedah, tugasan kepadanya akan menyebabkan rujukan Integer asal dihalakan ke alamat tindanan dalam kaedah, kehilangan penunjuk ke alamat pembolehubah kelas asal. Sebarang operasi yang dilakukan pada objek Integer yang ditetapkan tidak akan menjejaskan objek asal.
Perihalan pautan

PHPzhong

test1.a = "567", perkara yang anda ubah di sini ialah atribut test1 objek yang dirujuk oleh

str = "word" Perkara yang anda ubah di sini ialah objek yang ditunjuk oleh pembolehubah rujukan str.

Ringkasnya, ada dua, Xiao Ming dan Xiao Hong Jika anda menggantikan tangan Xiao Ming dengan tangan robot, tangan Xiao Ming benar-benar akan ditukar, tetapi jika anda menukar nama Xiao Hong kepada Xiao Ming... Xiao Hong sendiri masih tidak berubah.

Deeper, Xiao Ming dan Xiao Hong akan menyertai acara ini tidak memerlukan anda mengetahui nama sebenar anda, jadi mereka diberikan nama kod A dan B. Pada masa ini, A telah cedera semasa melakukan aktiviti dan pemegangnya digantikan dengan yang mekanikal Akibatnya, selepas aktiviti itu, tangan Xiao Ming sememangnya telah digantikan dengan yang mekanikal. Tetapi B baru sahaja menukar tanda nama kepada C. Selepas keluar, Xiao Hong masih lagi Xiao Hong dan belum menjadi orang yang sepadan dengan C.

Di sini, aktiviti ialah kaedah, dan kod yang ditetapkan ialah parameter formal Penetapan langsung nilai kepada parameter formal tidak akan menjejaskan parameter sebenar, tetapi memberikan nilai kepada sifat objek yang dirujuk oleh. parameter formal sebenarnya telah mempengaruhi sifat objek.


Saya akan menambah sekeping kod dengan ulasan untuk melihat sama ada ia boleh membantu anda memahami. Jika anda ingin memahami bahawa proses sebenar panggilan kaedah juga melibatkan pengetahuan seperti timbunan, ia tidak begitu rumit. Kod ini tidak mempunyai output Anda boleh cuba menambah beberapa output selepas memahaminya untuk mengesahkan sama ada pemahaman anda betul.

public class PassReferByValue  
{  
    String a = "123";  
    public static void test(PassReferByValue test)  
    {  
        test.a = "abc";  
    }  
    
    public static void test2(PassReferByValue test) {
        test = new PassReferByValue();
        test.a = "cde";
    }
    
    public static void test3(String s) {
        s = "world";
    }
  
    public static void main(String[] args)  
    {
        PassReferByValue obj = new PassReferByValue();

        // -----------------------------------------------
        // test(obj);       
        // 如果把这个调用过程展开,代码就像这样(为了便于识别,我改了下变量名

        // 说明一下:下面用 { } 代码段主要是为了限定里面的变量作用域
        // 进入 test(obj);
        {
            PassReferByValue test = obj;
            test.a = "abc";
        }
        // 没有返回类型,所以这里方法直接结束,出来
        
        // ------------------------------------------------
        // 现在来展开 test2(obj);
        {
            PassReferByValue test = obj;
            test = new PassReferByValue();  // test 是一个新对象,不是 obj 了
            test.a = "cde";     // 改变的是新对象,对 obj 没有影响
        }
        // 所以方法调用结束之后 obj 还是没变,还是 obj.a.equals("abc");
        
        // -------------------------------------------------
        // 现在来看 string 的情况
        String hello = "hello";
        // 这里开始展开 test3(hello);
        {
            String s = hello;
            s = "world";    // 这里修改了 s 引用的对象,但没有修改 hello 引用的对象
            // 所以 hello.equals("hello"), s.equals("world");
        }
    }
} 
洪涛

Lulus mengikut nilai, lulus dengan rujukan

PHPzhong

Kecuali untuk String, Objek lain dalam Java diluluskan melalui rujukan.

小葫芦
//示例2:String类型
public class Test  
{  
    public static void test(String str)  
    {  
        //str这个变量作用域在test这个函数里,原本指向"hello",现在指向"word"
        str = "word";  
    }  
  
    public static void main(String[] args)  
    {  
        String string = "hello";  
        System.out.println("对象的数据的初始值是:" + string);  //hello  
        test(string);  
        System.out.println("通过调用test方法修改对象的值之后还是以前的值:" + string);  //hello  
    }  
}

Saya menyebut perkara pengetahuan yang berkaitan pada permulaan salah satu lajur saya memandangkan anda agak keliru, saya ingin mengesyorkannya kepada anda.

阿神

Rentetan ialah jenis tidak berubah, yang bermaksud nilainya tidak berubah. Contohnya, String a = "abc", dalam ingatan, rujukan a menghala ke blok memori "abc". Apabila menggunakan a = "bcd", nilai blok memori di mana "abc" terletak tidak ditukar kepada "bcd", tetapi rentetan lain dihasilkan "bcd", dan kemudian arahkan a ke "bcd", jadi rujukan di luar kaedah masih menunjuk ke memori "abc".

Jenis pembolehubah secara langsung akan mengubah suai nilai memori di mana "abc" terletak Dengan cara ini, rujukan di luar kaedah masih menghala ke alamat memori asal, jadi nilai yang diubah suai boleh diakses di luar kaedah.

阿神

Rentetan yang terkandung dalam objek String tidak boleh diubah suai Apabila pembolehubah jenis String ditetapkan semula, rujukannya juga akan berubah dan menjadi objek baharu.

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan