String类型传值以及对象传值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package Virtual; class Stan{ String mm = "hello" ; } class Virtual { public static void main(String[] args) { Stan s= new Stan(); System.out.println(s.mm); change(s); System.out.println(s.mm); } public static void change(Stan s) { s.mm= "say" ; //其实是改变了mm指向字符串的地址,从指向hello的地址改成指向say的地址,hello还是存在,只是没有指向它 } } |
mm刚开始指向的是hello那一片内存,当传入change函数里,对象是原对象的引用,可以直接指向原对象mm的地址,此时如果将s.mm改成say,由于String类型是不可改变的,只能为say重新分配一片内存空间,并且将mm的值指向say的内存,所以输出会改变,
1 | 其实是改变了String对象 mm指向字符串的地址,从指向hello的地址改成指向say的地址,hello还是存在,只是没有指向它 |
再看下一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package Virtual; class Stan{ String mm = "hello" ; } class Virtual { public static void main(String[] args) { String s= "123" ; System.out.println(s); change(s); System.out.println(s); } public static void change(String s) { s= "say" ; } } |
此时s并没有被更改,这是为什么呢?因为传入函数时,是复制了一个String对象副本,这个String对象指向了say的内存空间,但是原String对象指向的还是123的内存空间,所以s并没有发生更改。String类型可以被认为是传值,即另外创建一个String对象,与原对象无关
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package Virtual; class Stan{ int temp= 10 ; } class Virtual { public static void main(String[] args) { Stan s= new Stan(); System.out.println(s.temp); change(s); System.out.println(s); } public static void change(Stan s) { s.temp= 30 ; } } |
这个跟例子1是一样的,也是传递对象的引用,即地址,并且temp是int型,可以被更改,所以直接改变temp所在的堆区的值为30
另外关于String类型的赋值还有对象的赋值还要说明,
1 2 3 4 5 6 7 8 9 10 11 12 | String s1 = "hello" ; String s2 = s1; //赋值在栈中,还是指向同一片内存,new在堆中自然指向不同内存 String s3 = new String(s1); new 在堆中自然指向不同内存 System.out.println(s1==s2); //返回值为true,说明指向的是同一片内存,因为hello储存在栈中,所以定义s2在栈中指向了同一片内存也就是hello的内存 System.out.println(s1==s3); //返回值为false,说明指向的是两片内存,因为new是在堆中分配内存,重新为hello在堆中分配了内存,原来的hello内存储存在栈中为改变 |
那么对象呢,对象的赋值就是引用
1 2 3 4 5 6 7 8 9 10 11 | MyObject myObject = new MyObject(); myObject.setName( "Hello" ); System.out.println(myObject.getName()); //输出Hello MyObject hisObject = myObject; //赋值初始化hisobject对象 hisObject.setName( "World" ); //改变了对象的名字属性 System.out.println(myObject.getName()); //输出World |
这说明了在对象赋值中是直接赋值了引用,改变hisObject的名字属性,相当于改变myObject的名字属性,相当于hisObject是MyObject的引用,两个对象指向的是同一片内存空间。
1 2 3 4 5 6 7 8 9 10 11 | MyObject myObject = new MyObject(); myObject.setName( "Hello" ); System.out.println(myObject.getName()); //输出Hello MyObject hisObject = new MyObject(); hisObject.setName( "World" ); System.out.println(myObject.getName()); //输出hello |
new对象,这个不用多说,其实是两个完全不相干的对象。
未经博主同意该原创文章不得转载
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步