首页 > 编程语言 >Java对象值传递和对象传递的总结

Java对象值传递和对象传递的总结

时间:2022-11-24 23:04:02浏览次数:38  
标签:Java String strBuf 对象 StringBuffer 传递 sb changeData Hello


值传递和对象传递的问题总结下。
     先看基本类型作为参数传递的例子:

public class Test1 {

public static void main(String[] args) {

int n = 3;

System.out.println("Before change, n = " + n);

changeData(n);

System.out.println("After changeData(n), n = " + n);

}

public static void changeData(int nn) {

nn = 10;

}

}


我想这个例子大家都明白,基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的,输出的结果证明了这一点:

Before change, n = 3

After changeData(n), n = 3


那么,我们现在来看看对象作为参数传递的例子,这也是大家争论的地方。

public class Test2 {

public static void main(String[] args) {

StringBuffer sb = new StringBuffer("Hello ");

System.out.println("Before change, sb = " + sb);

changeData(sb);

System.out.println("After changeData(n), sb = " + sb);

}

public static void changeData(StringBuffer strBuf) {

strBuf.append("World!");

}

}


先看输出结果:

Before change, sb = Hello 

After changeData(n), sb = Hello World!






从结果来看,sb的值被改变了,那么是不是可以说:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。从上面例子的输出结果来看,这样解释是合理。
现在我们对上面的例子稍加改动一下:

public class Test3 {

public static void main(String[] args) {

StringBuffer sb = new StringBuffer("Hello ");

System.out.println("Before change, sb = " + sb);

changeData(sb);

System.out.println("After changeData(n), sb = " + sb);

}

public static void changeData(StringBuffer strBuf) {

strBuf = new StringBuffer("Hi ");

strBuf.append("World!");

}

}


按照上面例子的经验:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。你会认为应该输出:

Before change, sb = Hello 

After changeData(n), sb = Hi World!






但运行一下这个程序,你会发现结果是这样的:

Before change, sb = Hello 

After changeData(n), sb = Hello






这就是让人迷惑的地方,对象作为参数传递时,同样是在方法内改变了对象的值,为什么有的是改变了原对象的值,而有的并没有改变原对象的值呢?这时候究竟是“传值”还是“传引用”呢?




下面就让我们仔细分析一下,来揭开这中间的奥秘吧。
先看Test2这个程序:
StringBuffer sb = new StringBuffer("Hello ");
这一句执行完后,就会在内存的堆里生成一个sb对象.sb是一个引用,里面存放的是一个地址“@3a”(这个“@3a”是我举的代表内存地址的例子,你只需知道是个内存地址就行了),而这个地址正是“Hello ”这个字符串在内存中的地址。




执行这一句后,就把sb传给了changeData方法中的StringBuffer strBuf,由于sb中存放的是地址,所以,strBuf中也将存放相同的地址,请看




此时,sb和strBuf中由于存放的内存地址相同,因此都指向了“Hello”。
strBuf.append("World!");




执行changeData方法中的这一句后,改变了strBuf指向的内存中的值,




所以,Test2 这个程序最后会输出:




After changeData(n), sb = Hello World!




再看看Test3这个程序。
没有执行到changeData方法的strBuf = new StringBuffer(“Hi “);之前,对象在内存中的图和上例中“图2”是一样的,而执行了strBuf = new StringBuffer(“Hi “);之后,则变成了:




此时,strBuf中存放的不再是指向“Hello”的地址,而是指向“Hi ”的地址“@3b” (同样“@3b”是个例子)了,new操作符操作成功后总会在内存中新开辟一块存储区域。
strBuf.append("World!");




而执行完这句后,




Hi World!
通过上图可以看到,由于sb和strBuf中存放地址不一样了,所以虽然strBuf指向的内存中的值改变了,但sb指向的内存中值并不会变,因此也就输出了下面的结果:
After changeData(n), sb = Hello
String类是个特殊的类,对它的一些操作符是重载的,如:
String str = “Hello”; 等价于String str = new String(“Hello”);
String str = “Hello”;
str = str + “ world!”;等价于str = new String((new StringBuffer(str)).append(“ world!”));
因此,你只要按上面的方法去分析,就会发现String对象和基本类型一样,一般情况下作为参数传递,在方法内改变了值,而原对象是不会被改变的。




综上所述,我们就会明白,在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。

 



 

值传递和对象传递的问题总结下。

     先看基本类型作为参数传递的例子:


public class Test1 {

public static void main(String[] args) {

int n = 3;

System.out.println("Before change, n = " + n);

changeData(n);

System.out.println("After changeData(n), n = " + n);

}

public static void changeData(int nn) {

nn = 10;

}

}


我想这个例子大家都明白,基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的,输出的结果证明了这一点:


Before change, n = 3

After changeData(n), n = 3


那么,我们现在来看看对象作为参数传递的例子,这也是大家争论的地方。


public class Test2 {

public static void main(String[] args) {

StringBuffer sb = new StringBuffer("Hello ");

System.out.println("Before change, sb = " + sb);

changeData(sb);

System.out.println("After changeData(n), sb = " + sb);

}

public static void changeData(StringBuffer strBuf) {

strBuf.append("World!");

}

}





先看输出结果:

Before change, sb = Hello

After changeData(n), sb = Hello World!






从结果来看,sb的值被改变了,那么是不是可以说:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。从上面例子的输出结果来看,这样解释是合理。


现在我们对上面的例子稍加改动一下:

public class Test3 {

public static void main(String[] args) {

StringBuffer sb = new StringBuffer("Hello ");

System.out.println("Before change, sb = " + sb);

changeData(sb);

System.out.println("After changeData(n), sb = " + sb);

}

public static void changeData(StringBuffer strBuf) {

strBuf = new StringBuffer("Hi ");

strBuf.append("World!");

}

}


按照上面例子的经验:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。你会认为应该输出:


Before change, sb = Hello 

After changeData(n), sb = Hi World!






但运行一下这个程序,你会发现结果是这样的:


Before change, sb = Hello 

After changeData(n), sb = Hello




这就是让人迷惑的地方,对象作为参数传递时,同样是在方法内改变了对象的值,为什么有的是改变了原对象的值,而有的并没有改变原对象的值呢?这时候究竟是“传值”还是“传引用”呢?






下面就让我们仔细分析一下,来揭开这中间的奥秘吧。


先看Test2这个程序:


StringBuffer sb = new StringBuffer("Hello ");


这一句执行完后,就会在内存的堆里生成一个sb对象.sb是一个引用,里面存放的是一个地址“@3a”(这个“@3a”是我举的代表内存地址的例子,你只需知道是个内存地址就行了),而这个地址正是“Hello ”这个字符串在内存中的地址。






执行这一句后,就把sb传给了changeData方法中的StringBuffer strBuf,由于sb中存放的是地址,所以,strBuf中也将存放相同的地址,请看






此时,sb和strBuf中由于存放的内存地址相同,因此都指向了“Hello”。


strBuf.append("World!");






执行changeData方法中的这一句后,改变了strBuf指向的内存中的值,






所以,Test2 这个程序最后会输出:






After changeData(n), sb = Hello World!






再看看Test3这个程序。


没有执行到changeData方法的strBuf = new StringBuffer(“Hi “);之前,对象在内存中的图和上例中“图2”是一样的,而执行了strBuf = new StringBuffer(“Hi “);之后,则变成了:






此时,strBuf中存放的不再是指向“Hello”的地址,而是指向“Hi ”的地址“@3b” (同样“@3b”是个例子)了,new操作符操作成功后总会在内存中新开辟一块存储区域。


strBuf.append("World!");






而执行完这句后,






Hi World!


通过上图可以看到,由于sb和strBuf中存放地址不一样了,所以虽然strBuf指向的内存中的值改变了,但sb指向的内存中值并不会变,因此也就输出了下面的结果:


After changeData(n), sb = Hello


String类是个特殊的类,对它的一些操作符是重载的,如:


String str = “Hello”; 等价于String str = new String(“Hello”);


String str = “Hello”;


str = str + “ world!”;等价于str = new String((new StringBuffer(str)).append(“ world!”));


因此,你只要按上面的方法去分析,就会发现String对象和基本类型一样,一般情况下作为参数传递,在方法内改变了值,而原对象是不会被改变的。






综上所述,我们就会明白,在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。


 

标签:Java,String,strBuf,对象,StringBuffer,传递,sb,changeData,Hello
From: https://blog.51cto.com/u_13991401/5885152

相关文章

  • Java的内存回收机制
    1.Java在内存中的状态首先我们先写一个代码为例子:Person.javapackagetest;importjava.io.Serializable;publicclassPersonimplementsSerializable{static......
  • java8 升级 java11 的一些bug
    1.反射异常有些反射异常,不是自己代码的错而是一些框架调用的时候,所带来的,不好处理。用压制输出的形式,1行为压制,2行为调试模式,输出所有的报错信息。这里用java.base/ja......
  • 在Spring Security中如何获取AuthenticationManager对象?
    有时需要使用AuthenticationManager(以下简称Manager)对象,可是这个对象不是Bean,没有直接保存在Spring的Bean库中。那么如何获取SpringSecurity中的这个对象呢?在SpringSecu......
  • 对象——原型
    每个对象都有原型原型里存着对象的共有属性比如obj的原型就是一个对象obj.__proto__存着这个对象的地址这个对象里有toString/construcor/valueOf等共有属性对象的......
  • java 反射 Reflection
    一.什么是反射:Relection(反射):是Java被视为动态语言的关键,反射机制允许程序在执行期间借助于ReflectionAPI取得任何类的内部信息,并能直接操作任意对象的内部属性及方法公式......
  • XmlHttpRequest对象创建于使用片段及处理字符串文本(Get)
    XmlHttpRequest对象创建于使用片段及处理字符串文本(Get)*.js//用户名校验的方法//这个方法将使用XMLHTTPRequest对象来进行AJAX的异步数据交互va......
  • XmlHttpRequest对象创建于使用片段及处理xml(Post)
    XmlHttpRequest对象创建于使用片段及处理xml.js//用户名校验的方法//这个方法将使用XMLHTTPRequest对象来进行AJAX的异步数据交互varxmlhttp;fu......
  • XmlHttpRequest对象创建于使用片段及处理字符串文本(Post)
    XmlHttpRequest对象创建于使用js//用户名校验的方法//这个方法将使用XMLHTTPRequest对象来进行AJAX的异步数据交互varxmlhttp;functionverify()......
  • Hutool介绍(详)Java工具类库
    Hutool介绍(详)于 2022-05-0510:40:12 首次发布版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。简介中文官网:https://plus.......
  • Java基础学习笔记(菜鸟教程版)
    Java基础学习笔记(菜鸟教程版)入门概览第一个Java程序helloworldpublicclassHello{publicstaticvoidmain(String[]args){/*pubic-->访问修饰符static-......