精华内容
下载资源
问答
  • 关于Java对象作为参数传递是传值还是传引用的问题

    万次阅读 多人点赞 2016-09-06 22:37:20
    前言 在Java中,当对象作为参数传递时,究竟传递的是对象的值,还是对象的引用,这是一个饱受争议的话题。若传的是值,那么函数接收的只是实参的一个副本,函数对形参的操作并不会对实参产生影响;若传的是引用,...

    前言

      在Java中,当对象作为参数传递时,究竟传递的是对象的值,还是对象的引用,这是一个饱受争议的话题。若传的是值,那么函数接收的只是实参的一个副本,函数对形参的操作并不会对实参产生影响;若传的是引用,那么此时对形参的操作则会影响到实参。
      首先我们来看一句代码:

    Object obj = new Object();
    

      这句话的意思是:创建一个Object对象,再创建一个名为obj的引用,让这个引用指向这个对象,如下图所示:

      1.png-4.3kB

    在有了上面的基础之后,我们便来看下面这组在网上很流行的例子:

    基本数据类型作为参数传递:

    例1:

    public class test {
        public static void main(String[] args) {
            int i = 1;
            System.out.println("before change, i = "+i);
            change(i);
            System.out.println("after change, i = "+i);
        }
        public static void change(int i){
            i = 5;
        }
    }
    

      这个例子不难理解,当基本数据类型作为参数传递时,传递的是实参值的副本,即传的是值,无论在函数中怎么操作这个副本,实参的值是不会被改变的。所以以上代码执行的结果是:
      
      before change, i = 1
      after change, i = 1
      
      

    对象作为参数传递:

      在下面的例2中,我们把StringBuffer对象作为参数传递到change函数。
      
      例2:

    public class test {
        public static void main(String[] args) {
            StringBuffer sb = new StringBuffer("Hello ");
            System.out.println("before change, sb is "+sb.toString());
            change(sb);
            System.out.println("after change, sb is "+sb.toString());
        }
        public static void change(StringBuffer stringBuffer){
            stringBuffer.append("world !");
        }
    }
    

      为了方便推理出结论,我们先直接看程序的运行结果:
      
      before change, sb is Hello
      after change, sb is Hello world !
      
      从输出结果中我们可以发现,sb所指向的对象的值被改变了,那么是否我们可以推论出,在Java中,当对象作为参数传递时,传递的是该对象的引用呢?我们再来看下面这个例子:
      
      例3:

    public class test {
        public static void main(String[] args) {
            StringBuffer sb = new StringBuffer("Hello ");
            System.out.println("before change, sb is "+sb.toString());
            change(sb);
            System.out.println("after change, sb is "+sb.toString());
        }
        public static void change(StringBuffer stringBuffer){
            stringBuffer = new StringBuffer("Hi ");
            stringBuffer.append("world !");
        }
    }
    

      如果上面的推论是正确的,即Java中对象作为参数传递,实际传递的是该对象的引用,那么在调用change函数之后,原对象的值应该是会改变的,变为“Hi world !”,但是,当我们运行程序后,结果却是如下所示:
      
      before change, sb is Hello
      after change, sb is Hello
      
      原对象的值并没有被改变,这与上面的推论相矛盾!为什么在Java中,当对象作为参数传递时,有的时候实参被改变了,而有的时候实参并未被改变呢?下面让我们来分析一下其中的原因:
      从文章的开头我们知道,当执行StringBuffer sb = new StringBuffer(“Hello “)时,我们创建了一个指向新建对象“new StringBuffer(“Hello “)”的引用“sb”,如下图所示:
      
      2.png-3.2kB
      
      在例2中,当我们调用change函数后,实际上,形参stringBuffer也指向了实参sb所指向的对象,即:
      
      3.png-6.3kB
      
      那么当我们执行stringBuffer.append(“world !”)后,便通过对象的引用“stringBuffer”修改了对象的值,使之变成了“Hello world !”,即:
      
      4.png-6.6kB
      
      但是,在例3中的change函数中,我们又新建了一个对象“new StringBuffer(“Hi “)”(这实际上在内存中开辟了一块在原对象地址之外的新区域),这让形参stringBuffer实际指向了这个新建的对象,并将新对象的值设置为“Hi world !”,即:
      
      image_1art4suka65r1m4o1a0spgcjr89.png-10.1kB
      
      那么我们就不难理解,为何在执行完change函数之后,实参的值仍为“Hello”了。
      

    结论

      综上所述,我们可以得出结论:在Java中,当对象作为参数传递时,实际上传递的是一份“引用的拷贝”。
      
      

    展开全文
  • Java编程中,当对象作为参数传递给方法时候,是按引用传递的,但是有的人会说这实质上是按值传递的。其实两者说的都不错,只是理解的方式不一样罢了,二者的原理其实是一样的。

    一、

    Java编程中,当对象作为参数传递给方法时候,是按引用传递的,但是有的人会说这实质上是按值传递的。其实两者说的都不错,只是理解的方式不一样罢了,二者的原理其实是一样的。


    二、

    下面通过一个例子来详细说明Java对象作为方法参数的时候会出现的情况:

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 测试java的引用传值
     *
     * Created by Xuyh at 2017/01/05 上午 10:27.
     */
    public class SetParamTest {
    	public static void main(String... args) {
    		// 集合对象,列表[a, b, c]
    		List<String> testParam = new ArrayList<String>();
    		testParam.add("a");
    		testParam.add("b");
    		testParam.add("c");
    		System.out.println("Old: " + testParam.toString() + "\r\n");
    
    		// 引用(地址)传值,并直接修改testParam指向对象的值
    		change(testParam);
    		System.out.println("Change1: " + testParam.toString() + "\r\n");
    
    		testParam.add("a");
    
    		// 引用(地址)传值,修改指向对象之后再将地址返回
    		testParam = change2(testParam);
    		System.out.println("Change2: " + testParam.toString() + "\r\n");
    
    		// 集合对象变为[b, c, d, e]
    		testParam.add("d");
    		testParam.add("e");
    
    		// 引用(地址)传值,方法内部new新集合对象并将地址赋给方法局部参数,
    		// 并不改变testParam的值,testParam仍然指向原地址
    		sort(testParam);
    		System.out.println("sort1: " + testParam.toString() + "\r\n");
    		// 引用(地址)传值,方法内部new新集合对象并将地址赋给方法局部参数,
    		// 并将新地址返回,再赋值给testParam,因此testParam指向的对象发生改变
    		testParam = sort2(testParam);
    		System.out.println("sort2: " + testParam.toString() + "\r\n");
    	}
    
    	public static void change(List<String> param) {
    		if (param.contains("a"))
    			param.remove("a");
    	}
    
    	public static List<String> change2(List<String> param) {
    		if (param.contains("a"))
    			param.remove("a");
    		return param;
    	}
    
    	public static void sort(List<String> param) {
    		List<String> newParam = new ArrayList<String>();
    		for (int i = param.size() - 1; i >= 0; i--) {
    			newParam.add(param.get(i));
    		}
    		param = newParam;
    	}
    
    	public static List<String> sort2(List<String> param) {
    		List<String> newParam = new ArrayList<String>();
    		for (int i = param.size() - 1; i >= 0; i--) {
    			newParam.add(param.get(i));
    		}
    		return newParam;
    	}
    }
    

    上面的例子简单的说就是一个列表,[a, b, c],首先通过两个方法把其中的字符”a”去除,然后通过两个方法对列表[b, c, d, e]进行倒序排序。同时在操作的过程中不断将main方法中的testParam输出出来。


    接着请看程序运行的结果:

    Old: [a, b, c]
    
    Change1: [b, c]
    
    Change2: [b, c]
    
    sort1: [b, c, d, e]
    
    sort2: [e, d, c, b]

    由结果可以看到,两个change方法都将原来的testParam改变了,而sort方法只有一个改变了testParam的值,这个有趣的现象接下来要好好说说了。下面从四个比较典型的方法来介绍不同情况下对象作为值传入方法时候内存中的情况,以便我们更好理解java的方法传值原理。


    三、

    change方法

    public static void change(List<String> param) {
    	if (param.contains("a"))
    		param.remove("a");
    }

    testParam作为参数传递给param时候,内存内是这样的:


    testParam的地址值复制给了change方法局部变量param,于是param指向了与testParam相同的一个对象。注意这时候param的引用(地址)值是testParam的一份拷贝。

     

    Change方法中将列表的”a”元素去除时候的情况是这样的:


    此时testParamparam指向的对象(同一个)发生了改变,所以方法执行完毕之后输出testParam是发生改变的。



    change2方法

    public static List<String> change2(List<String> param) {
    	if (param.contains("a"))
    		param.remove("a");
    	return param;
    }

    change方法类似,当对象在方法中发生改变时候,内存中的情况是这样的:


    testParam = change2(testParam);

    方法执行到最后,param会返回,也就是param的引用(地址)值会返回,然后又拷贝给testParam(其实是多此一举,二者的地址值完全相同)。所以方法执行完成之后输出的testParam是发生改变的。



    sort方法

    public static void sort(List<String> param) {
    	List<String> newParam = new ArrayList<String>();
    	for (int i = param.size() - 1; i >= 0; i--) {
    		newParam.add(param.get(i));
    	}
    	param = newParam;
    }

    调用方法时候内存中是这样的


    接着,方法中new了一个新的对象,并在处理排序之后将新对象的引用(地址)赋值给param,这时候内存中的情况是这样的:


    可以看到,testParamparam指向的已经不是同一个地址了,并且testParam指向的对象仍然没有发生改变。因此方法执行完毕之后输出的结果看来,sort方法是没有用的。



    sort2方法

    public static List<String> sort2(List<String> param) {
    	List<String> newParam = new ArrayList<String>();
    	for (int i = param.size() - 1; i >= 0; i--) {
    		newParam.add(param.get(i));
    	}
    	return newParam;
    }

    sort方法类似,执行sort2方法前内存中是这样的:


    新对象排序完成后是这样的:


    这时候testParamparam都是指向原来的对象

    方法的最后把newParam返回,即将newParam的引用(地址)值返回,在main方法中将其赋值给testParam

    testParam = sort2(testParam);

    然后内存中就是这样的了:



    因此经过返回后的sort2方法是有作用的。



    四、

    小结:

    通过以上的分析可以得出,Java中对象作为方法参数传递的是对象引用(地址)值的拷贝,通俗的讲,就是拷贝了一把钥匙,main方法中的钥匙跟被调用方法中参数的钥匙对应能打开的房间是相同的,但是是不同的钥匙。如果在被调用方法中,参数钥匙被修改了(new了一个新对象并赋值给参数钥匙),不会影响main方法钥匙指向的房间。这点是值得注意的。

     

    因此如果想要在被调用方法中不修改参数指向的对象,可以通过new一个新的对象来实现,但是如果想要new一个新的对象并使main方法该对象变成这个新的对象,就要将其作为返回值返回并赋值给旧对象变量了。




























    展开全文
  • Java中接口对象作为参数传递

    千次阅读 2016-05-23 18:56:14
    Java中接口对象作为参数传递(小例子)


           

         第一步想用接口作为参数 首要的条件就是要有接口,定义一个接口

    <pre name="code" class="java">         public interface A{
                  public void helloWorld();
             }

     
    

         第二步:有了接口,必须有实现接口的类

    <pre name="code" class="java">               public class B implements A{
                        public void helloWorld(){
                        System.out.println("世界,您好!");
                        }
                   }


     
       
      第三步:有了前边的准备工作当然就要有将A接口作为参数的类了
     
    

    <pre name="code" class="java">             public class C {
                         public void helloTest (A a){
                                a.helloWorld();
    
                        }
            
                     }


     
         
     
    第四步:
    就是客户端的调用了
    

    public class Client{
         public static void main(String[] args){
          C   c = new C();
    //向上转型
          A  b  = new B();
    
           c.helloWorld(b);
    
          }
    }

       第五步: 程序结果

    世界,您好!
    展开全文
  • java中String对象作为参数传递问题

    千次阅读 2020-06-03 15:24:04
    java中将对象作为参数传递究竟是值传递还是引用传递? 1、基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的。 2、对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了...

    问题

    java中将对象作为参数传递究竟是值传递还是引用传递?
    1、基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的。
    2、对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。

    且看下面代码
    首先我们有一个Student类,它有两个成员变量nameage

    package test_code;
    public class Student {
        String name;
        int age;
        public Student(String name,int age){
            this.name = name;
            this.age = age;
        }
    }
    

    Student对象进行参数传递,运行如下代码

    package test_code;
    public class method_test {
        public static void main(String[] args) {
            Student s = new Student("jack",16);
            test(stu);
            System.out.println(stu.age);
        }
        public static void test(Student s)
        {
            s.age = 22;
        }
    }
    

    请问输出是16还是22呢?
    答案是22,因为对象进行参数传递时是将对象的地址拷贝了一份传给s,也就是说方法中的s和传入的stu指向的是同一个对象,通过s.age将值进行修改了那么stu.age的值也相应被修改了。这很容易理解。


    那么当String类对象进行参数传递时,运行如下代码

    package test_code;
    public class method_test {
        public static void main(String[] args) {
            String str = "111";
            test(str);
            System.out.println(str);
        }
        public static void test(String s)
        {
            System.out.println(s);
            s = "222";
            System.out.println(s);
        }
    }
    

    请问输出是什么呢?
    答案是222吗?不对。
    那么为什么答案是111呢?
    问题就在s = "222";这一行上。
    这一行执行后,s和str所指向的对象就不是一个了。为什么呢?
    由于Java中String对象不可改变的特性,这里其实是在常量池中新开辟了一块区域给222使用,s指向了222,但是并没有改变str的指向,那么str自然是111了。

    本文较为简单,但希望能够大家带来一定的启发,大家在工作学习中一定要多多思考,欢迎关注,一起进步。

    展开全文
  • java 对象作为方法的参数传递

    万次阅读 2018-03-24 14:45:25
    说到对象作为方法的参数传递的时候,大家都知道,当方法有返回值的时候,我们在其他方法定义一个接收他的对象就把他的值给获取到了,可是如果不定义对象接收呐?请看方法有返回值的情况下:这种情况下,打印出来的值...
  • Java对象作为参数传递给一个方法时,实际上传递的是这个对象引用的拷贝,被拷贝的引用和拷贝的引用指向同一个内存地址,即同一个对象 所以如果在方法中改变参数引用(拷贝的引用)指向的内存地址,对方法外的引用是...
  • 用简单类型作为参数就是把参数个数和类型写死,改动影响大,如果使用对象传参,就很灵活,但传递对象的效率会差一点,这两种方式该如何取舍?
  • java中将对象作为参数的本质

    千次阅读 2009-04-23 10:31:00
    面试时碰到过许多关于java方法中传递对象参数的问题,关于java中传递参数,总结如下: a.传递值类型参数,如基本数据类型,不可以改变变量的值. b.传递对象类型参数,可以改变对象变量的实例域值. c.传递对象...
  • JAVA在方法中对象作为参数传递

    千次阅读 2018-02-23 17:42:35
    但是在java中,将方法A中的某个对象传递到方法B中进行修改后,再返回到A中,我们会发现对象在B中的修改在A中也有效。示例代码如下:有一个bean类:public class DemoBean { private String id; pu...
  • 当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象引用的一个副本。指向同一个对象对象的内容可以在被调用的方法中改变,但是对象的引用(不是引用的副本)是永远不会改变的。 Java参数:...
  • 1.实现方式说明 本文在---- 手写redis @ Cacheable注解支持过期时间设置 的基础之上进行扩展。 1.1问题说明: ...目前方法的第一个参数Java对象,但是原注解只支持Java的的基本数据类型。 1.2实现...
  • java中把对象作为参数传递的理解

    万次阅读 2017-12-29 14:24:12
    只不过,当把对象作为参数传递时,可以通过该副本引用改变该对象的的属性。 而我上面程序在方法里 issuePublishDate = null; 这里已经对变量重新赋值了。此时的变量 issuePublishDate 已经不再是参数传进来的那个...
  • java对象作为参数传递给一个方法,到底是值传递,还是引用传递? pdd:所谓java只有按值传递:基本类型 值传递;引用类型,地址值传递,所以叫值传递。  当主函数的变量,对象(主本)传递到副函数时,传递的...
  • java对象作为参数传递一般是引用传递,基本变量传值方式是值传递。但是字符串作为一个对象传递却意外的是值传递。 先定义值传递意义:就是讲原先的基本变量或者引用拷贝一份,作为参数传递给函数。特点是当函数...
  • 因为对象参数往往是引用传参形式,所以很多时候,我们往往会通过调用一个函数,然后直接想当然的认为该值已经发生变化,然而,情况并非如此,这得需要看看方法里到底做了些什么,请看下边这个例子: private ...
  • 又是一道面试题,来测试你的Java基础是否牢固。 题目:以下代码的运行结果是? public class TestValue { public static void test(String str) { str="World"; //代码3 } public static void main(String...
  • 先执行匿名类的构造方法,在运行外面以匿名对象作为参数的方法。 在看公司大神写的代码时,因为用到了很多匿名对象,匿名对象的构造方法里面又嵌套了很多方法和匿名对象,看的时候很头疼,不知道具体的运行流程,...
  • JAVA接口作为参数传递

    万次阅读 多人点赞 2011-07-20 18:02:55
    可以将接口类型的参数作为方法参数,在实际是使用时可以将实现了接口的类传递给方法,后方法或按照重写的原则执行,实际调用的是实现类中的方法代码体,这样便根据传进入的参数的不同而实现不同的功能。重要的是,当...
  • 方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。 下面举例说明...
  • 学习Java的过程中,很容易将对象对象引用混为一谈,而且我们平时在交流时为了方便起见也只是对象怎样、对象怎样,但很多时候我们操作的,根本上来说是对象,但直接操作的却是对象的引用。 先贴一篇博文,非常形象...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 752,078
精华内容 300,831
关键字:

java对象作为参数

java 订阅