精华内容
下载资源
问答
  • Java参数传递方式

    千次阅读 2014-10-25 09:49:28
    Java参数传递方式分为基本类型参数传递和对象类型参数传递。

    原文:http://blog.sina.com.cn/s/blog_59ca2c2a0100qhjx.html,我作了些修改并增加了一个实例,增加对比

    本文通过内存模型的方式来讨论一下Java中的参数传递。


    1、基本类型参数的传递方式

    这里的内存模型涉及到两种类型的内存:栈内存(stack)和堆内存(heap)。基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。看下边的一段代码,然后结合内存模型来说明问题:

    public class ParameterTransfer {
     public static void main(String[] args) {
      int num = 30;
      System.out.println("调用add方法前num=" + num);
      add(num);
      System.out.println("调用add方法后num=" + num);
     }
     
     public static void add(int param) {
      param = 100;
     }
     
    }
    这段代码运行的结果如下:
    调用add方法前num=30
    调用add方法后num=30
        

    程序运行的结果也说明这一点,无论你在add()方法中怎么改变参数param的值,原值num都不会改变。
    下边通过内存模型来分析一下。
    当执行了int num = 30;这句代码后,程序在栈内存中开辟了一块地址为AD8500的内存,里边放的值是30,内存模型如下图:


     执行到add()方法时,程序在栈内存中又开辟了一块地址为AD8600的内存,将num的值30传递进来,此时这块内存里边放的值是30,执行param = 100;后,AD8600中的值变成了100。内存模型如下图:   


    地址AD8600中用于存放param的值,和存放num的内存没有任何关系,无论你怎么改变param的值,实际改变的是地址为AD8600的内存中的值,而AD8500中的值并未改变,所以num的值也就没有改变。

    2、对象类型参数的传递方式

    1)先看下边的示例代码:

    public class ParameterTransfer {
     public static void main(String[] args) {
      String[] array = new String[] {"huixin"};
      System.out.println("调用reset方法前array中的第0个元素的值是:" + array[0]);
      reset(array);
      System.out.println("调用reset方法后array中的第0个元素的值是:" + array[0]);
     }
     
     public static void reset(String[] param) {
      param[0] = "hello, world!";
     }
     
    }
    运行的结果如下:
    调用reset方法前array中的第0个元素的值是:huixin
    调用reset方法后array中的第0个元素的值是:hello, world!
    当对象作为参数传递时,传递的是对象的引用,也就是对象的地址。下边用内存模型图来说明。


    当程序执行了String[] array = new String[] {"huixin"}后,程序在栈内存中开辟了一块地址编号为AD9500内存空间,用于存放array[0]的引用地址,里边放的值是堆内存中的一个地址,示例中的值为BE2500,可以理解为有一个指针指向了堆内存中的编号为BE2500的地址。堆内存中编号为BE2500的这个地址中存放的才是array[0]的值:huixin。
    当程序进入reset方法后,将array的值,也就是对象的引用BE2500传了进来。这时,程序在栈内存中又开辟了一块编号为AD9600的内存空间,里边放的值是传递过来的值,即AD9600。可以理解为栈内存中的编号为AD9600的内存中有一个指针,也指向了堆内存中编号为BE2500的内存地址,如图所示:


    这样一来,栈内存AD9500和AD9600(即array[0]和param的值)都指向了编号为BE2500的堆内存。
    在reset方法中将param的值修改为hello, world!后,内存模型如下图所示:


    改变对象param的值实际上是改变param这个栈内存所指向的堆内存中的值。param这个对象在栈内存中的地址是AD9600,里边存放的值是BE2500,所以堆内存BE2500中的值就变成了hello,world!。程序放回main方法之后,堆内存BE2500中的值仍然为hello,world!,main方法中array[0]的值时,从栈内存中找到array[0]的值是BE2500,然后去堆内存中找编号为BE2500的内存,里边的值是hello,world!。所以main方法中打印出来的值就变成了hello,world!

    2)我们再来看个例子

    class Dog{
    	int x,y;
    	int z=1;
    	Dog(int x,int y){
    		this.x=x;
    		this.y=y;
    	}
    	void move1(Dog d){
    		d.x=d.x+10;
    		d.y=d.y+10;
    	}
    	void move2(Dog d){
    		Dog d2=new Dog(100, 100);
    		d=d2;
    		
    	}
    }
    public class UseDog {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Dog d1=new Dog(10,10);
    		d1.move2(d1);
    		System.out.print(d1.x+","+d1.y+":");
    		d1.move1(d1);
    		System.out.println(d1.x+","+d1.y+";");
    	}
    
    }
    输出结果为:10,10:20,20;

    先解释10,10:当执行d1.move2(d1)时,d1(引用地址)传入move2中,栈内存开辟空间存入。之后新建对象d2,并将d2(引用地址)赋给d,那么d就指向了对象d2。因此并未改变d1所指向的堆内存值。

    再解释20,20:当执行d1.move1(d1)时,d1(引用地址)传入move1中,栈内存开辟空间存入,即d指向了d1所指向的堆内存值。这时在move1中改变d所指向的对象的值,那么d1所指向的对象值也改变了。因为d和d1指向的是同一个对象。


    3、总结

    无论是基本类型作为参数传递,还是对象作为参数传递,实际上传递的都是值,只是值的的形式不用而已。第一个示例中用基本类型作为参数传递时,将栈内存中的值30传递到了add方法中。第二个示例中用对象作为参数传递时,将栈内存中的值BE2500传递到了reset方法中。当用对象作为参数传递时,真正的值是放在堆内存中的,传递的是栈内存中的值,而栈内存中存放的是堆内存的地址,所以传递的就是堆内存的地址。这就是它们的区别。

    补充一下,在Java中,String是一个引用类型,但是在作为参数传递的时候表现出来的却是基本类型的特性,即在方法中改变了String类型的变量的值后,不会影响方法外的String变量的值。关于这个问题,可以参考如下两个地址:
    http://freej.blog.51cto.com/235241/168676
    http://dryr.blog.163.com/blog/static/58211013200802393317600/
    我觉得是这两篇文章中提到的两个原因导致的,一个是String实际上操作的是char[],可以理解为String是char[]的包装类。二是给String变量重新赋值后,实际上没有改变这个变量的值,而是重新new了一个String对象,改变了新对象的值,所以原来的String变量的值并没有改变。

    展开全文
  • JAVA参数传递方式

    2020-12-09 14:41:47
    java语言只有值传递java语言只有值传递java语言只有值传递! 基本类型 基本类型的传递过程包含“求值”、“拷贝”、“传递”三个过程,这样使得对形参的改变不会体现到实参上。 对象类型 每个可用的对象都...

    java语言只有值传递!
    java语言只有值传递!
    java语言只有值传递!

    基本类型

    • 基本类型的传递过程包含“求值”、“拷贝”、“传递”三个过程,这样使得对形参的改变不会体现到实参上。

    对象类型

    • 每个可用的对象都有一个或者多个引用指向这个对象,在实参传递给形参的过程中,和基本数据类型一样,会对实参引用执行“求值”、“拷贝”、“传递”三个过程,这样形参可以获取到原引用的一个拷贝,同基本数据类型一样,修改引用与对象之间的引用关系,不会体现到实参引用上。
    • 由于实参、形参指向同一个对象,所以通过不同引用都能操作到同一个对象,这样对于对象的传递,看起来和引用传递表现地一样,同时,因为本身作为值传递,不会破环不同引用的引用关系。

    总结

    • java仅包含值传递

    • 基本类型属于值传递

    • 对象类型也属于值传递,传递的是引用本身——它是值传递的一种特殊形式,可以称之为“传共享对象调用(共享对象传递)”。

      • 它保留了值传递的特性——不会破环不同引用各自的引用关系(“引用关系的更改”对于实参和形参之间是不可见的)。
      • 同时实现了引用传递的特性:通过引用操作对象时,操作结果对于形参和实参都是可见的。
    • 特殊性:String类,由于String在赋值的时候(更直接地说:更改的时候),会创建新对象(常量池中不存在时)。

      • 所以它保留了“共享对象传递”传递的特性(对引用直接赋值,不会破坏其它引用与对象间的引用关系)

      • 同时,通过特殊的赋值操作,看起来跟操作基本数据类型一样(“更改”对于实参和形参之间是不可见的)。对String引用进行赋值的时候,实际上是改变了引用与对象间的引用关系,这样就和基本类型表现是一致的。

        ==================================================================================
        采用什么方式传递值,只是程序语言设计的过程中采用了不同的求值策略,关于求值策略个人也不甚了解。关于是都采用值传递,个人观点是:在传递过程中是否发生了“拷贝”操作,可以拷贝值本身,也可以拷贝引用(这里的引用只java中的引用,不是C++中的),欢迎指正!

    展开全文
  • java 参数传递方式

    2010-03-30 00:30:00
    网上有个很经典的java32问,其中有一题问java参数传递方式是按值还是按引用,一般答案都说是按值。对此我有一些疑惑,查了相关资料,终于基本弄清楚了。下面是一个测试:Java代码 public class People { private ...

    网上有个很经典的java32问,其中有一题问java参数传递方式是按值还是按引用,一般答案都说是按值。对此我有一些疑惑,查了相关资料,终于基本弄清楚了。下面是一个测试:

    Java代码 复制代码
    1. public class People   
    2. {   
    3.     private int age;   
    4.     private String name;   
    5.   
    6.     public People(String name, int age)   
    7.     {   
    8.         this.age = age;   
    9.         this.name = name;   
    10.     }   
    11.   
    12.     public void show()   
    13.     {   
    14.         System.out.println(getName()+":"+getAge());   
    15.            
    16.     }   
    17.   
    18.     public int getAge()   
    19.     {   
    20.         return age;   
    21.     }   
    22.   
    23.     public String getName()   
    24.     {   
    25.         return name;   
    26.     }   
    27.   
    28.     public void setAge(int age)   
    29.     {   
    30.         this.age = age;   
    31.     }   
    32.   
    33.   
    34.     public void setName(String name)   
    35.     {   
    36.         this.name = name;   
    37.     }   
    38.   
    39. }  
    public class People
    {
    	private int age;
    	private String name;
    
    	public People(String name, int age)
    	{
    		this.age = age;
    		this.name = name;
    	}
    
    	public void show()
    	{
    		System.out.println(getName()+":"+getAge());
    		
    	}
    
    	public int getAge()
    	{
    		return age;
    	}
    
    	public String getName()
    	{
    		return name;
    	}
    
    	public void setAge(int age)
    	{
    		this.age = age;
    	}
    
    
    	public void setName(String name)
    	{
    		this.name = name;
    	}
    
    }

     

    Java代码 复制代码
    1. public class Main   
    2. {   
    3.     public static void main(String[] args)   
    4.     {   
    5.         int i =9;   
    6.         String s = "ppp";   
    7.         People aaa = new People("aaa",40);   
    8.            
    9.         modifyInt(i);   
    10.         modifyString(s);   
    11.         modifyObject(aaa);   
    12.            
    13.         System.out.println(i);   
    14.         System.out.println(s);   
    15.         aaa.show();   
    16.   
    17.     }   
    18.     private static void modifyInt(int i)   
    19.     {   
    20.         i = 40;   
    21.     }   
    22.     private static void modifyString(String str)   
    23.     {   
    24.         str = "sss";   
    25.     }   
    26.     private static void modifyObject(People aaa)   
    27.     {   
    28.         aaa.setAge(11);   
    29.         aaa.setName("ooo");    
    30.     }   
    31. }  
    public class Main
    {
    	public static void main(String[] args)
    	{
    		int i =9;
    		String s = "ppp";
    		People aaa = new People("aaa",40);
    		
    		modifyInt(i);
    		modifyString(s);
    		modifyObject(aaa);
    		
    		System.out.println(i);
    		System.out.println(s);
    		aaa.show();
    
    	}
    	private static void modifyInt(int i)
    	{
    		i = 40;
    	}
    	private static void modifyString(String str)
    	{
    		str = "sss";
    	}
    	private static void modifyObject(People aaa)
    	{
    		aaa.setAge(11);
    		aaa.setName("ooo");	
    	}
    }

     输出结果:

    Java代码 复制代码
    1. 9  
    2. ppp   
    3. ooo:11  
    9
    ppp
    ooo:11

     由此可见,基本类型和String类型并没有发生变化,它们是按值传递的;而一般对象发生了变化,可以说是按引用传递的。但为什么有人说对象也是按值传递的呢?理解的角度不同,他们所理解的值并不是指整个对象的具体内容,而是对象的引用(引用是什么东西呢?说白了,就是对象存储的地址,这个地址以值拷贝的方式传到了形参中,“值传递”指的就是这个)。其实对象是分两部分存储的,一个是对象引用,也就是对象在内存中的地址,存储在栈里(基本类型也是存储在栈里,栈里的东西都是值拷贝),另外一个是对象的内容,存储在堆里。

    另外,我们发现String类型很奇怪,它具有基本类型的很多特点,原因之一就是它是final修饰的,既然不可变,那么执行str = "sss"时必然要new新的String,str里存放的是新的String的地址。

    展开全文
  • java参数传递方式

    2009-03-15 18:44:38
    网上有个很经典的java32问,其中有一题问java参数传递方式是按值还是按引用,一般答案都说是按值。对此我有一些疑惑,查了相关资料,终于基本弄清楚了。下面是一个测试: public class People { private int age; ...

    网上有个很经典的java32问,其中有一题问java参数传递方式是按值还是按引用,一般答案都说是按值。对此我有一些疑惑,查了相关资料,终于基本弄清楚了。下面是一个测试:

    public class People
    {
    	private int age;
    	private String name;
    
    	public People(String name, int age)
    	{
    		this.age = age;
    		this.name = name;
    	}
    
    	public void show()
    	{
    		System.out.println(getName()+":"+getAge());
    		
    	}
    
    	public int getAge()
    	{
    		return age;
    	}
    
    	public String getName()
    	{
    		return name;
    	}
    
    	public void setAge(int age)
    	{
    		this.age = age;
    	}
    
    
    	public void setName(String name)
    	{
    		this.name = name;
    	}
    
    }
     
    public class Main
    {
    	public static void main(String[] args)
    	{
    		int i =9;
    		String s = "ppp";
    		People aaa = new People("aaa",40);
    		
    		modifyInt(i);
    		modifyString(s);
    		modifyObject(aaa);
    		
    		System.out.println(i);
    		System.out.println(s);
    		aaa.show();
    
    	}
    	private static void modifyInt(int i)
    	{
    		i = 40;
    	}
    	private static void modifyString(String str)
    	{
    		str = "sss";
    	}
    	private static void modifyObject(People aaa)
    	{
    		aaa.setAge(11);
    		aaa.setName("ooo");	
    	}
    }

     输出结果:

    9
    ppp
    ooo:11

     由此可见,基本类型和String类型并没有发生变化,它们是按值传递的;而一般对象发生了变化,可以说是按引用传递的。但为什么有人说对象也是按值传递的呢?理解的角度不同,他们所理解的值并不是指整个对象的具体内容,而是对象的引用(引用是什么东西呢?说白了,就是对象存储的地址,这个地址以值拷贝的方式传到了形参中,“值传递”指的就是这个)。其实对象是分两部分存储的,一个是对象引用,也就是对象在内存中的地址,存储在栈里(基本类型也是存储在栈里,栈里的东西都是值拷贝),另外一个是对象的内容,存储在堆里。

    另外,我们发现String类型很奇怪,它具有基本类型的很多特点,原因之一就是它是final修饰的,既然不可变,那么执行str = "sss"时必然要new新的String,str里存放的是新的String的地址。

    展开全文
  • Java 参数传递方式

    2017-09-22 21:32:06
    1. 方法内修改基础数据类型(数字类型或布尔类型)不会改变方法外的参数。 2. 方法内修改对象(包含数组)状态会同步修改方法方法外的参数。 3. 方法不能改变对象参数的引用。
  • 主要介绍了JAVA参数传递方式,结合实例形式分析了java按值传递与引用传递区别及相关操作注意事项,需要的朋友可以参考下
  • Java参数传递方式(值传递和引用传递)之终极奥义 首先确定一点:Java是值传递 在讨论Java方法传递的是值还是引用之前,我们先看一下概念: 1、值传递:在方法被调用时,实参通过形参把它的内容副本传入方法内部,...
  • 在C等其他语言中经常会遇到以下两种参数传递方式: 值传递:方法调用时,实际参数将它的值传递给形式...在Java中的参数传递方式都是值传递,当参数类型为int等基本数据类型时直接将值传递给形参;当参数为String、对
  • java参数传递方式问题

    千次阅读 2014-04-24 08:20:02
    java参数传递方式究竟是值传递还是引用传递一直是个备受争论的问题,在这里,我给出了自己的一些理解,纯属个人意见,仅供参考。
  • Java参数传递方式前言一、Java到底是值传递还是引用传递?值传递引用传递基本类型值传递,引用类型引用传递值传递(对象内容引用传递)二、图解1.String图解2.对象图解总结 前言 今天上班后摸鱼知乎的时候,突然...
  • 说明Java参数为值传递 输出结果为: methodOne a =101 main a =100     demo2:   public static void methodTwo(List a) { a.add( 101 ); } public static void main(String[] ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,835
精华内容 1,534
关键字:

java参数传递方式

java 订阅