Java的按值传递和引用传递

来源:互联网 发布:京东金融 免费数据 编辑:程序博客网 时间:2024/06/16 22:30

1、引用类型


   要理解什么是值传递和引用传递首先必须理解什么是引用类型,之前我也是有着很模糊的概念,感觉懂了,但是实际更深层次的理解还是会出现问题。

   (1)、什么是引用类型   引用类型(reference type)指向一个对象,不是原始值,指向对象的变量是引用变量。   在java里面除去基本数据类型和String的其它类型都是引用数据类型,自己定义的class类都是引用类型,可以像基本类型一样使用。   (2)、引用类型的赋值   在java编程语言中,用类的一个类型声明的变量被指定为引用类型,这是因为它正在引用一个非原始类型,这对赋值具有重要的意义。如下代码
    int x = 7;    int y = x;    String s = "Hello";    String t = s;   
    四个变量被创建:两个原始类型 int 和两个引用类型String。x的值是7,而这个值被复制到y;x和y是两个独立的变量且其中任何一个的进一步的变化都不对另外一个构成影响。至于变量s和t,只有一个String对象存在,它包含了文本"Hello",s和t均引用这个单一个对象。

2、按值传递和按引用传递

    在基本类型中,在内存中存储的是值,而在引用类型中存储的是地址,

(1)、按值传递

   指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下:
   public class Test {       private void test(int num) {          num++;          System.out.println("test方法中的num=="+num);      }      public static void main(String args[]) {           Test t = new Test();           int num = 3;           t.test(num);//这里传递的参数a就是按值传递。           System.out.println("main方法中的num===" + num);        }    }  

控制台打印结果:

test方法中的num==4
main方法中的num===3


    按值传递的重要特点是:传递的是值的拷贝,可以这么通俗的理解,    基本类型存储的是值,我的值可以给你但是只能给你复制一份,你拿去随便怎么使用,但是你不能贪得无厌还想对我的值做什么操作,而且按值传递在main()方法中声明的int类型的num变量和在test()方法中传入的num不是同一个num,相当于在传入的时候重新定义了一个num,我自己的num在调用t.test(num)的时候可以把我存储的值复制给你,test方法中对num进行操作也是你自己操作自己的num,在main方法打印的还是我的num,你不能对我做任何操作,在test方法执行完成之后,你的num会被回收,因为我没有使用的你的num。

(2)、按引用传递

 按引用传递指的是在方法调用时,传递的参数是按引用进行传递,其实传递的是引用的地址,也就是变量所对应的内存空间的地址。

代码示例如下:

  public class Test {    private void test(User user) {        user.setUsername("木易");        System.out.println("test方法中的username  :"+user.getUsername());    }    public static void main(String args[]) {        User user=new User("muyi");        System.out.println("在进行引用传递之前的username  :"+user.getUsername());        Test test=new Test();        test.test(user);        System.out.println("在进行引用传递之后的username  :"+user.getUsername());        System.out.println("");    }}class User{    private String username;    public User(String username) {        this.username = username;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }}  
 按引用传递的重要特点是:在传递过程中都指向了同一个引用(也就是同一片内存空间)。

简单通俗的说就是,我在main()方法中定义了一个User类的对象user并通过new()的方式给user分配了一片内存空间,可以理解为user与地址空间 “相等”了,如何理解new()方法中的 “ = ” 很关键啊,User的引用user指向User空间地址,我在main()方法中调用test方法传递user 的时候,传的就是我的引用的地址(因为user “等于” 地址嘛),还是老规矩,test()方法中定义的user也不是原来的user,只是声明了一个同一类型的变量,但是它和我指向了同一个引用,所以他也可以改变值,相当于我拉了一个合伙人和我一起操作。

但是另一种情况,代码示例:

private void test(User user) {        user = new User("杨");        System.out.println("test方法中的username  :"+user.getUsername());    }

我们只是修改了test()方法里面一点内容。
但是运行结果就不一样了:

在进行引用传递之前的username :muyi
test方法中的username :杨
在进行引用传递之后的username :muyi

   这是因为我们在test方法中另外给他分配了一片地址空间,他就不指向原来的user引用了。所以他们操作互不干扰。   可以这么理解:在第一种情况中:User user(test)= user(main);进行了两步操作,先是定义了一个User引用,user(test),然后在main中把user(main)赋值给他 。所以相当于是 user(test)=user(main)=new User();所以指向了同一片地址空间。但是在第二种情况中,我们在test()方法中又给user(test)分配了一个地址空间,相当于覆盖了原来的地址空间,所以他们不再指向同一片地址空间。

参考博客:

他画得内存模型图很好,我就是参考这篇博客

这也是我第一次写博客,因为平时学的知识很碎,不记录一下的话很容易忘记。希望各位大神指正其中不足之处。

原创粉丝点击