`
rockyuse
  • 浏览: 195421 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

java参数传递时到底是值传递还是引用传递(baidu搜集)

 
阅读更多

最近学习java,由于受以前c++的影响,对java 的参数传递方法搞不清楚,随Google之,baidu之。看了下面两篇文章,若有所悟,得到下面的结论


(1)对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的,如果在函数中修改了参数的引用,那函数后如果不是return,则改变不会生效,如果return了,则改变后传给return后的值。

 

(2)对于原始数据类型,也就是int、 long、char之类的类型,是传值的,如果你在方法中修改了值,方法调用结束后,那个变量的值没用改变。 

(3)对于对象类型,也就是Object的子类,如果你在方法中修改了它的成员的值,那个修改是生效的,方法调用结束后,它的成员是新的值,但是如果你把它指向一个其它的对象,方法调用结束后,原来对它的引用并没用指向新的对象。 

 

java参数传递时到底是值传递还是引用传递(baidu搜集)

最近比较长一段时间以来,网上的IT同行里面比较流行JAVA面试32问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其有一道题让我很费解。

原题是:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

google查询结果,得到答案基本上是:值传递。当时觉得挺纳闷儿,为什么连参数的内容都被修改了,怎么还能说是“值传递”呢?因为在传统的印象里(尤其是从C++过来以后),值传递都应该是不改变原参数的。

问问周围的同事,也大都这么讲,但是也都讲不清这种理论的根源是什么。我这个人有个毛病,有事情想不通时就会憋得难受,后来在《Thinking in Java》的一段内容(注解[1])里找到了自己的结论,我认为(《Thinking in Java》的作者也这么认为):可以说是值传递,也可以说是引用传递。

一,认为是值传递。得出这种结论的前提必须是“参数的值就是对该对象的引用,而不是对象的内容”,这句话可能有些费解,举个例子加以说明。

public class Paier {

     public static void main(String[] args) {

                    Paier paier = new Paier();

                    paier.test();

     }

    

     public void test() {

                    TestClass para1 = new TestClass();

                    para1.setTest(new Integer(10));

                    TestClass result1 = test1(para1);

                    System.out.println("para1   = " + para1.getTest());

                    System.out.println("result1 = " + result1.getTest());

                   

                    TestClass para2 = new TestClass();

                    para2.setTest(new Integer(10));

                    TestClass result2 = test2(para2);

                    System.out.println("para2   = " + para2.getTest());

                    System.out.println("result2 = " + result2.getTest());

     }

    

     public TestClass test1(TestClass t) {

                    t = new TestClass();

                    t.setTest(new Integer(20));

                    return t;

     }

    

     public TestClass test2(TestClass t) {

                    t.setTest(new Integer(20));

                    return t;

     }

    

     class TestClass {

                    Integer test = null;

                    public void setTest(Integer i) {

                                  test = i;

                    }

                    public Integer getTest() {

                                  return test;

                    }

     }

}

执行后的结果是:

para1   = 10

result1 = 20

para2   = 20

result2 = 20

为什么会这样呢?因为test1想通过修改参数的引用来修改返回值,但是在JAVA中,参数的引用是不可修改的,所以para1result1分别指向不同的空间,结果也不一样。而在test2中,result2para2始终指向同一块区域,test2方法修改的是参数内容,而不是参数的引用。

从上面看来,因为参数的引用不可改变,如果理解为“参数的值就是对该对象的引用”,那么java自然只有值传递。

二,认为是引用传递。还是上面的例子,如果在参数传递时理解为“参数的值就是该对象的内容”,那么显然不是值传递,因为对象的内容已经改变了。

认为是引用传递还有一个理由,就是java有一个保留字byvalue现在的JDK版本中还没有实现这个保留字,似乎是在暗示对这种观点的支持。(There appears to be some support for this view within Sun, since one of the “reserved but not implemented” keywords is byvalue.

所以说,对于原题的结论,是值传递还是引用传递并不重要,重要的是要理解“对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。”

 

注解[1]:下面是在《Thinking in Java》中的原文:

This brings up the terminology issue, which always seems good for an argument. The term is “pass by value,” and the meaning depends on how you perceive the operation of the program. The general meaning is that you get a local copy of whatever you’re passing, but the real question is how you think about what you’re passing. When it comes to the meaning of “pass by value,” there are two fairly distinct camps:

1.      Java passes everything by value. When you’re passing primitives into a method, you get a distinct copy of the primitive. When you’re passing a handle into a method, you get a copy of the handle. Ergo, everything is pass by value. Of course, the assumption is that you’re always thinking (and caring) that handles are being passed, but it seems like the Java design has gone a long way toward allowing you to ignore (most of the time) that you’re working with a handle. That is, it seems to allow you to think of the handle as “the object,” since it implicitly dereferences it whenever you make a method call.

2.      Java passes primitives by value (no argument there), but objects are passed by reference. This is the world view that the handle is an alias for the object, so you don’t think about passing handles, but instead say “I’m passing the object.” Since you don’t get a local copy of the object when you pass it into a method, objects are clearly not passed by value. There appears to be some support for this view within Sun, since one of the “reserved but not implemented” keywords is byvalue. (There’s no knowing, however, whether that keyword will ever see the light of day.)

Having given both camps a good airing and after saying “It depends on how you think of a handle,” I will attempt to sidestep the issue for the rest of the book. In the end, it isn’t thatimportant – what is important is that you understand that passing a handle allows the caller’s object to be changed unexpectedly.


文章二

转自:http://www.jiehoo.com/java-pass-parameter.htm 

Java参数传递方式 

其实这个问题我原来翻译(破除java神话之二:参数是传址的 )、转帖别人的详细解释(Java 应用程序中的按值传递语义 )和专门解释( 我对《Java 应用程序中的按值传递语义》的理解)过,不过现在看来,原来翻译或者解释的角度是有问题的,从底层的角度解释并不直观,在交流的时候也容易引起误解,最终不能达成一致意见。下面以最终的效果来解释参数的传递方式: 


1、对于原始数据类型,也就是int、 long、char之类的类型,是传值的,如果你在方法中修改了值,方法调用结束后,那个变量的值没用改变。 

2、对于对象类型,也就是Object的子类,如果你在方法中修改了它的成员的值,那个修改是生效的,方法调用结束后,它的成员是新的值,但是如果你把它指向一个其它的对象,方法调用结束后,原来对它的引用并没用指向新的对象。 

代码如下: 

public class Tester { 

    public static void main(String[] args) { 

        int primitive = 2; 

        changePrimitive(primitive); 

        //primitive的值依然是2 

        MyClass myClass = new MyClass(); 

        changeObject(myClass); 

        //myClass仍然指向的是执行changeObject之前的那个对象 

        //但是myClass.i等于3了 

    } 


    public static void changePrimitive(int primitive) { 

        primitive = 3; 

    } 


    public static void changeObject(MyClass myClass) { 

        myClass.i = 3; 

        myClass = new MyClass(); 

    } 


class MyClass { 

    int i; 


对于远程调用,无论是什么类型,调用结束后,传入的参数和以前没用任何变化(当然前途是直接调用远程方法,如果中间经过其它的Proxy类或者Facade类,不能保证那些类对对象没用修改)。至于是通过Locale接口进行调用的,我不太清楚是否属于远程调用。以后确定了再来更新。 

分享到:
评论

相关推荐

    Java的23种设计模式百度云下载链接.rar

    Java 8中的Stream API中,`Collectors`类提供了多种收集策略。 21. **模版方法模式**:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。Java中的`AbstractClass`和`abstract`方法就是模板方法模式的...

    Java基础知识笔记.rar

    5. **方法**:掌握方法的定义、参数传递(按值传递和按引用传递)以及返回值。 6. **类与对象**:理解面向对象编程的基本概念,包括类的定义、对象的创建、封装、继承和多态性。 7. **构造器**:了解构造函数的...

    百度NLPNIP java sdk

    在使用百度NLPNIP Java SDK时,我们需要依赖几个关键的库文件,如log4j-1.2.17.jar、aip-java-sdk-4.1.1.jar和json-20160810.jar。其中,`log4j`是一个广泛使用的日志记录框架,用于收集和记录程序运行过程中的信息...

    java就业班全套课程

    - **函数与方法**:学会定义和调用函数,理解参数传递机制。 - **面向对象编程**:深入理解类与对象的概念,熟悉封装、继承、多态三大特性。 #### 2. 数据库技术 - **SQL语言**:熟练掌握SQL查询语句的编写,如...

    最新版jdk 8【百度网盘】

    Lambda允许以更简洁的方式表示匿名函数,可以作为参数传递,也可以作为返回值。这使得处理集合和并发编程变得更加便捷。 2. **方法引用和构造器引用**:与Lambda表达式紧密关联,它们提供了一种直接引用已有方法或...

    Java核心技术 11版 卷1 卷2 英文版

    4. **方法**:讨论方法的定义、参数传递和返回值,以及如何使用方法来组织和重用代码。 5. **类与对象**:深入解释面向对象编程的基本概念,如封装、继承和多态,以及如何通过类和对象来实现这些概念。 6. **数组...

    项目中添加百度统计

    此外,百度统计还提供了崩溃日志报告功能,可以自动收集应用崩溃时的错误信息。只需在Application的onCreate方法中开启即可: ```java StatService.setCrashReportEnabled(this, true); ``` 如果你的应用支持推送...

    JAVA面试葵花宝典.zip

    - **方法与封装**:理解方法的作用,学会参数传递和返回值的处理,以及封装的原则。 2. **面向对象** - **类与对象**:理解类的定义、对象的创建及生命周期,以及类的继承、多态性。 - **封装**:了解访问修饰符...

    JRE1.8.txt

    Lambda表达式是Java 8中最重要的新特性之一,它允许开发者将行为作为方法参数传递,使得代码更加简洁、易读。流API则提供了一种新的数据处理方式,它可以高效地处理集合、数组等数据结构。 ##### 2. 方法引用 方法...

    2023一线互联网大厂Java面试题集

    它包含了来自百度、阿里、字节跳动等知名企业的最新面试题目,涵盖了广泛的Java核心技术领域。 1. **Java基本数据类型**: - Java的八种基本数据类型包括整型(byte, short, int, long)、浮点型(float, double)...

    Java分布式项目实战视频

    根据提供的文件信息,我们可以深入探讨有关“Java分布式项目实战”的一系列关键知识点。下面将围绕该主题展开详细讨论,包括但不限于分布式系统的定义、Java在分布式系统中的应用、分布式系统设计原则与模式、实战...

    jdk1.8中文版(百度翻译系列)wh.rar

    Lambda允许将函数作为方法参数传递,或者以更简洁的方式实现接口。 2. **Stream API**:新的Stream API提供了处理集合的新方法,如filter、map和reduce,使数据操作更为流畅。Stream API支持串行和并行处理,有助于...

    java 在线生成二维码

    5. **生成二维码**:在`getQRCode()`函数中,用户输入的数据被组合成一个VCARD字符串,然后将这个字符串作为参数传递给生成二维码的函数。在这个例子中,使用了一个名为`jquery.MyQRCode.js`的JavaScript插件,该...

    一步步教你用Java爬虫爬取CSDN文章.zip

    在本教程中,我们将深入探讨如何使用Java编程语言来实现一个简单的网络爬虫,以便从CSDN(China Software Developer Network)网站上抓取并保存文章。CSDN是一个知名的中文IT技术社区,包含了大量的技术文章和资源。...

    java源码Java聊天室程序(java)

    根据提供的文件信息,我们可以推断出这份资源是一个Java编写的聊天室程序的源代码,并且可以通过百度网盘链接获取到。接下来,我们将基于这个信息展开更详细的解释与知识点的介绍。 ### Java聊天室程序概述 Java...

    基于JAVA的电子商务系统分析与设计(共27页).docx

    【基于JAVA的电子商务系统分析与设计】 随着互联网的迅速发展,电子商务系统已成为现代商业不可或缺的一部分。本系统以JAVA为技术基础,旨在构建一个图书专卖店的在线销售平台,满足消费者便捷购书的需求。用户可以...

    UdacityJavaCourse:Udacity Java 课程存储库

    5. **函数**:掌握函数的定义、参数传递和返回值,理解函数重载和递归。 6. **异常处理**:学习如何捕获和处理程序运行时可能出现的错误,以提高代码的健壮性。 7. **文件I/O**:了解如何读写文件,实现数据的持久...

    kafka所需java的jar

    JAR(Java Archive)是Java平台的一种归档格式,它用于收集多个类文件和其他资源,如图像、声音或文本文件,以便一起分发和运行。在Kafka和Spring MVC的场景中,这些JAR文件包含了必要的库和API,使得开发者可以方便...

    百度地图开发java源码-tools:工具

    本文将深入探讨“百度地图开发java源码-tools”这一主题,包括相关工具、推荐书籍、热修复技术、浏览器插件开发、客服系统构建、日志分析、页面设计、软件工程实践以及JDK 8和深度学习的应用。 首先,对于百度地图...

    Android应用发布后的统计——百度移动统计的应用

    params.putString("参数名1", "参数值1"); params.putInt("参数名2", 123); BaiduMobStatSDK.event(this, "事件名称", params); ``` **Channel统计** 是另一个关键功能,用于追踪应用的推广效果。在发布应用时,...

Global site tag (gtag.js) - Google Analytics