`
zhang85836131
  • 浏览: 9773 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
文章分类
社区版块
存档分类
最新评论

(转)关于java函数传值还是传引用的经典问题

阅读更多
看到的一个解释这个问题的帖子,有那么点意思啊呵呵:

经典的问题,但却不容易弄懂,尤其对有c基础的java程序员来说,更容易引起混乱,这里我试图简单点描述。

“java函数是传值的,java函数传递的参数是对象的引用”

这两句话好像初听上去有些矛盾,但却是事实,因而引起很多初学者的混乱。在这里我试图据个简单的例子来说明java的这个特性,可能不全面,希望大家来补全。


public class TestRef {

    

    public static void main(String[] args)

    {

        ValueObject vo1 = new ValueObject("A", 1);

        System.out.println("after vo1: " + vo1.getName()); //=A

        

        changeValue1(vo1);

        System.out.println("after changeValue1: " + vo1.getName());

        //=A1, changed

        

        changeValue2(vo1);

        System.out.println("after changeValue2: " + vo1.getName()); 

        //=A1, changeValue2内部的赋值不会影响这里。

    }



    /**

     * 使用vo1自身的函数对其内部数据进行改变是有效的,函数外可反映出来

     * 这种object称为可变的(mutable)

     * @param vo1

     */

    private static void changeValue1(ValueObject vo1) {

        vo1.setName("A1");

    }



    /**

     * 在函数内给vo1重新赋值不会改变函数外的原始值

     * @param vo1

     */

    private static void changeValue2(ValueObject vo1) {

        vo1 = new ValueObject("B", 2);

        System.out.println("inside changeValue2: "+ vo1.getName());

        //=B,赋值操作引起的结果变化仅在changeValue2内部有效

    }

}



class ValueObject {

    

    public ValueObject() {}

    

    public ValueObject(String name, int id)

    {

        this.name = name;

        this.id = id;

    }

    

    private String name;

    private int id;

    public int getId() {

        return id;

    }

    public void setId(int id) {

        this.id = id;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

}


解释,vo1作为一个object,当它被用作函数参数的时候传递给函数的是一个引用值,这个名称有点怪,又有引用又有值,到底是引用还是值呢,就看你怎么理解了。如果你是去考试,官方的答案是值。可是看起来又象引用啊,希望从这个例子,你能理解java参数传递和和C/C++程序中的引用传递的不同的地方。另外,这也是java作为OO语言的特性之一:封装的体现。

先讲一下对象赋值的关系,举例来说,下列代码:

ValueObject v2, v3;
v2 = new ValueObject("C", 3); 粗体的部分创建了一个数据结构,假设存放在内存地址A000,赋值给句柄 v2
v3 = new ValueObject("D", 4); 粗体的部分创建了一个数据结构,假设存放在内存地址B000,赋值给句柄 v3
v2 = v3; 这句话的作用是把操作B000的地址的句柄的值付给了v2的句柄,使得v2和v3一样操作B000的地址,这意味着:
1.原来v2指向的地址A000变成无主的内存地址,将自动被jvm回收。
2.既然v2和v3指向同一片地址,对v3的修改v2也能得到,反之亦然。

整理得下列代码,请感兴趣的朋友运行验证
ValueObject v2 = new ValueObject("C", 3);
ValueObject v3 = new ValueObject("D", 4);
v2 = v3;
System.out.println("after v2=v3");
System.out.println("v2= "+ v2.getName());//=D
System.out.println("v3= "+ v3.getName());//=D
v3.setName("C1");
System.out.println("after v3 setnameTo C1");
System.out.println("vo2= "+ v2.getName());//=C1
System.out.println("vo3= "+ v3.getName());//=C1


因此,可以得出结论,java中对象的每个实例(instance, 比如vo1, v2, v3 都是ValueObject的实例)的内存地址是唯一的,它一旦被创建,能够对这个地址进行操作的就是每个实例自己,如果ValueObject类中没有public void setName之类的方法对这个类的实例中的数据进行修改的话,程序是没有任何别的方法可以修改ValueObject类的实例中的数据,这个就是java的封装特性。对于不提供修改内部数据的方法的类,我们称为不可变(immutable)的类。在函数中对传入的参数变量进行赋值操作,只能在函数范围内改变局部变量指向的引用地址,但是不会改变原始地址的内容。因此,在changeValue2(...)函数内部的vo1和函数外的vo1虽然名字相同,但是实际上是不同的实例变量,只不过指向了和函数外的vo1同样的地址,所以当我们用vo1=... 对其进行赋值的时候,只不过是把函数内的临时变量指向了新的地址,并没有改变原始vo1内存地址中的内容。这就是在运行changeValue2(...)之后,vo1的值在main范围内仍然没有被修改的原因。而changeValue1里面是调用的ValueObject本身的function来更改其内容,因此是原始内存地址中的数据被更改了,所以是全局有效的。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/shikai1030/archive/2007/01/31/1499244.aspx
分享到:
评论

相关推荐

    java中传值还是传引用的的认识

    "java中传值还是传引用的认识" Java 中的参数传递是值传递还是引用传递?这是一个经常引发讨论的问题。在 Java 中,参数传递是按值传递的,也就是说,传递给方法的参数是一个副本,而不是原始值本身。 当一个对象...

    java中传值与传引用

    在Java编程语言中,函数调用时的参数传递方式有两种:传值(Passing by Value)和传引用(Passing by Reference)。虽然Java官方文档中并未明确指出有传引用这一概念,但在实际操作中,Java的行为类似于传引用,尤其...

    java的传值与传值后的改变

    在Java编程语言中,"传值与传值后的改变"是一个关键的概念,涉及到函数调用时参数的传递方式。在Java中,有两种基本的数据类型:原始类型(如int, double, char等)和引用类型(如类实例、数组)。它们在函数调用时...

    引用类型传值方法

    引用类型的传值行为体现在函数调用和方法参数传递上。当我们把一个引用类型变量作为参数传递给函数时,并不会创建该对象的新副本,而是复制了这个引用。这意味着函数内部对对象的任何修改都会影响到原始对象,因为...

    Java中的传值与传引用实现过程解析

    Java中的传值与传引用是Java编程语言中的一种基础概念,它们是Java函数中参数传递的两种方式。 Java中的传值是指函数参数的值被复制到函数内部,在函数内部对参数的修改不会影响原来的参数值。 Java中的传引用是指...

    23.Java对象作为参数传递是传值还是传引用1

    在Java编程语言中,关于Java对象作为参数传递时的行为,存在一种常见的误解。许多人认为对象是按引用传递,而实际上,Java总是按值传递,包括对象。这里的“值”指的是对象的引用,而不是对象本身。这与C++或C#等...

    java及C++中传值传递、引用传递和指针方式的理解.docx

    ### Java及C++中传值传递、引用传递和指针方式的理解 在程序设计语言中,函数调用时参数的传递方式对理解程序的行为至关重要。本文将深入探讨Java与C++这两种广泛使用的编程语言中参数传递的方式,包括值传递、引用...

    分析java的传值问题

    ### 分析Java中的传值问题 在Java编程语言中,函数调用时参数传递的方式是理解程序行为的关键之一。本文将深入探讨Java中基本类型与引用类型的数据传递机制,并通过具体的示例代码来阐述这两者之间的区别。 #### ...

    Java的引用和函数参数传递

    ### Java的引用与函数参数传递详解 #### 一、Java中的引用基础 在Java中,对象的引用扮演着类似于其他编程语言(如C/C++)中指针的角色,但是Java的引用比传统的指针更加安全且易于管理。这是因为Java的设计者们...

    Android NDK底层和java代码相互传值调用(实用经典Demo)

    对于自定义对象,我们需要先定义一个Java类的本地结构体(JNI类型为`jclass`),然后使用`GetObjectClass`获取类引用,`GetMethodID`获取方法ID,最后通过`CallVoidMethod`等函数调用方法。例如,传递一个自定义的`...

    传值传名传地址.zip

    传名在Python中可以被视为一种特殊形式的传引用,因为Python中的所有对象都是引用类型,函数调用时传递的是对象的引用。这意味着,即使在函数内部修改形参,也会直接影响到实参。 最后,我们来探讨**传地址**。传...

    python 函数传参之传值还是传引用的分析

    Python不支持像C++或Java那样的纯粹的值传递或引用传递,而是采用了独特的“传对象引用”方式。这种方式结合了值传递和引用传递的特点,但又有所不同。 在Python中,所有的变量都是对象的引用。当我们传递一个变量...

    42.传值和传引用.doc-综合文档

    在编程领域,传值和传引用是两种不同的参数传递机制,它们主要应用于函数调用时对参数的处理。本文将详细探讨这两种机制及其在不同编程环境中的应用,以C++、Java、C#等文本编程语言和LabVIEW可视化编程语言为例。 ...

    Java参数传递PPT

    Java参数传递机制是编程中的重要概念,尤其是在Java中,它对于理解如何在方法间操作数据至关重要。本PPT深入探讨了这一主题,旨在帮助学习者彻底理解Java中的参数传递方式。 首先,我们要回顾面向对象的基本概念。...

    Java语言的方法参数浅析

    通过对典型程序的研究与分析可以看出JAVA语言的参数传递总是传值调用的,但是对于基本类型的参数和对象类型的参数来说,参数传递的情况不完全相同.Java语言不能直接使用传引用调用,但是可以通过数组的方式模拟传引用...

    Java计算机语言函数应用

    下面我们将深入探讨Java函数的应用及其相关知识点。 1. **函数定义与调用** - 函数的基本结构包括返回类型、函数名、参数列表和函数体。例如,`public int add(int a, int b) { return a + b; }` 定义了一个名为`...

    Java函数与数组实验源代码

    方法的参数传递可以是传值或传引用,理解这一点有助于避免潜在的错误。返回类型则表示函数执行后的结果类型,它可以是基本类型或对象。 递归是函数调用自身的技术,常用于解决需要重复执行相同任务的问题。例如,...

    java类

    ### Java 类:传值还是传引用? 在Java编程语言中,理解变量的传递方式对于编写高效、可维护的代码至关重要。本文将通过一个具体的例子来深入探讨Java中的传值与传引用的区别,并解释如何利用这一特性来更好地管理...

    Java中参数传值的代码清单.pdf

    Java只支持两种类型的参数传递:基本数据类型(如int、double等)的传值和引用类型(如类对象)的传值。以下是对给定代码清单的详细解释: 1. **基本数据类型传值**: 在Java中,基本数据类型的参数传递是按值传递...

    基于传值test.rar

    在Java中,函数调用时参数的传递有两种方式:传值(Pass by Value)和传引用(Pass by Reference)。传值是指函数接收的是变量副本的一个拷贝,而不是实际的变量本身。这意味着,当函数内部修改参数时,不会影响到...

Global site tag (gtag.js) - Google Analytics