`
tianya85
  • 浏览: 34605 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

call by value 和call by reference

阅读更多

关于JAVA中参数传递问题有两种,一种是按值传递(如果是基本类型),另一种是按引用传递(如果是對象).

 

首先以两个例子开始:

1)
public class Test2 {

public static void main (String [] args) {
StringBuffer a = new StringBuffer ("A");
StringBuffer b = new StringBuffer ("B");
operate (a,b);
System.out.println(a+","+b);
}

static void operate(StringBuffer x, StringBuffer y){
     x.append(y);
     y = x;
   }
}
输出:AB,B

2)
public class Test2 {

public static void add3 (Integer i){
      int val=i.intValue();
      val += 3;
      i = new Integer (val);
}

public static void main (String args [ ] ) {
Integer i = new Integer (0);
add3 (i);
System.out.println (i.intValue ( ));
}
}
输出:0

首先我们应该明白JAVA中的参数传递全是以值传递的。是基本类型,就拷贝一个基本类型传进方法;是引用,就拷贝一个引用变量传进去方法,理解了这 两点就能理解方法操作对象的相关问题了。最好能画出引用指向对象的图出来,就能完全理解了。
第1题,调用operate方法时,传入了两个引用a,b的拷贝x,y,这两个x,y都指向原a,b引用所指向的对象。x.append(y)对它指向的 对象(即a指向的对象)进行了操作。而x=y,只是两个拷贝变量在赋值,并没有影响到原b所指向的对象。所以b所指向的对象仍然为B。
第2题,i=new Integer(val)只是一个引用的拷贝指向了另外一个对象,而原来的i仍然是指向对象new Integer(0)的。
把握住了JAVA都是传值并且传的都是拷贝的话,类似的题大家都能迎刃而解了。

 

Java中的参数传递只有一种方式: by value. 理论说教太麻烦了,直接看些例子吧:
1). 基本类型
    public class A{
   public static void main(String[] args){
       int x = 1;
       System.out.println(x);    //1
       test(x);
       System.out.println(x);    //还是1==>By value
   }
  
   static void test(int a){
      a = 2;
   }
}

2). 引用类型
    public class B{
   public static void main(String[] args){
       Integer x = new Integer(1);
       System.out.println(x);
       test(x);
       System.out.println(x);
      
   }
  
   static void test(Integer a){
      a = new Integer(2);
   }
}

理解这里的关键是区分对象和引用。 这里声明的x是一个引用,而不是一个对象(只是Java把它设计为看上去好像是对象一样)。这个引用它指向了一个对象,这个对象就是后面用new关键字生 成的对象。因此,可以说x指向了一个Integer对象。
在调用test方法的时候,程序将x作为参数传递给test方法了。这里仍然是值传递在test调用过程中,会产生一份新的引用(不妨叫做y)。此 时,x和y指向了同一个对象。
   x和y指向的是同一个对象, 由于Java的设计,我们可以通过操作引用来达到操作对象的目的。因此,如果我们此时使用y来修改对象的属性 (例如,y.someField++); 你可以看到x指向的对象同时也被修改到了。
   另一方面,如果我们让y指向另外一个对象, y=new Integer(2); 此时x和y就指向了不同的
对象。y修改了它指向的对象的属性,很显然不会影响到x指向的对象

 

有人说了数组。数组也是一个引用类型,它的参数传递方式按照引用类型的参数传递一样可以解释得通:

import java.util.Arrays;

public class A{
   public static void main(String[] args){
      int[] aa = {3, 2, 1};
      System.out.println(Arrays.toString(aa)); //[3, 2, 1]
      test(aa);
      System.out.println(Arrays.toString(aa)); //[3, 2, 1]
      test2(aa);
      System.out.println(Arrays.toString(aa)); //[4, 2, 1]
   }
  
   static void test(int[] a){
      a = new int[]{1, 2, 3};   //指向了新对象
   }
  
   static void test2(int[] a){
     if(a != null && a.length > 0)
       a[0]++;              //修改原来的那个对象
   }
}

 

 

对象是传引用(call by reference),简单类型是传值(call by value),不要被网上的一些概念所迷惑!!!你可以自己做个试验。
至于String等类型传的还是引用。如果你用concat方法,String对象的原值就会被改变。
但你如果按如下方法:
public class Test {
    public static void test(String str) {
        str = "World";
    }
    public static void main(String[] args) {
        String string = "Hello";
        test(string);
        System.out.println(string);
    }
}

  运行结果:Hello
这里str = "World" 就等同于 String str=new String("World")。所以结果没有改变!!!

下列程序在1处是否会有异常,如果没有,输出是什么?是否会运行到2处,如果会,输出是什么?为什么会有这样的结果?

 

  import java.util.arraylist;
   import java.util.list;
  
   public class testclass {


   public static void main(string args[]) {
     list list = new arraylist();
     test2(list);
     system.out.println(list.size()); // 1处
     test3(list);
     system.out.println(list.size()); // 2处
   }
  
   public static void test2(list list) {
     list = null;
   }
  
   public static void test3(list list) {
      list.add(“aaaa“);
   }
   }

plumechen:

不会出错的。结果是0,1。

因为test2(list)传得是list的引用,我理解成指针置的副本,list=null;只是把那个传入的值设置为null,不改变原来 list的指针和内容。test3(list)传入的一样,但是执行了list.add()由于传入指针值的副本也指向原来的那个list的地址,所以原 来的那个list的内容就改变了,size变成了1了

 

 

 6.下列正确的有()

  A. call by value不会改变实际参数的数值

  B. call by reference能改变实际参数的参考地址

  C. call by reference不能改变实际参数的参考地址

  D. call by reference能改变实际参数的内容

  答案:ACD

 

 

Java中的参数传递只有一种方式: 值传递 (by value)

1、简单类型类型,在调用的方法中,直接是实参的一个拷贝

2、对象:程序将对象x作为参数传递给方法了。这里仍然是值传递在方法调用过程中,会产生一份新的引用(不妨叫做y)。此时,x和y指向了同一个对象。

我们可以通过操作引用来达到操作对象的目的。 因此,如果我们此时使用y来修改对象的属性 (例如,y.someField++); 你可以看到x指向的对象同时也被修改到了。(值传递,在方法里产生引用,操作引用达到操作对象。所以引用可以修改实参(对象)的内容)

 

实验

 

package callbyvalue;

//public class Test2 {
//
//    public static void main (String [] args) {
//    StringBuffer a = new StringBuffer ("A");
//    StringBuffer b = new StringBuffer ("B");
//    operate (a,b);
//    System.out.println(a+","+b);          //AB,B
//    }
//
//    static void operate(StringBuffer x, StringBuffer y){  //JAVA中的参数传递全是以值传递的。
//        //是基本类型,就拷贝一个基本类型传进方法;是引用,就拷贝一个引用变量传进去方法
//         x.append(y);  //x.append(y)对它指向的对象(即a指向的对象)进行了操作
//         y = x;    //只是两个拷贝变量在赋值      并不会影响原来的对象
//         System.out.println(y);    //AB
//       }
//    }


//public class Test2 {
//
//    public static void add3 (Integer i){
//          int val=i.intValue();
//          val += 3;
//          i = new Integer (val);  //只是一个引用的拷贝指向了另外一个对象,而原来的i仍然是指向对象new Integer(0)的
//    }
//
//    public static void main (String args [ ] ) {
//    Integer i = new Integer (0);
//    add3 (i);
//    System.out.println (i.intValue ( ));  //0
//    }
//    }



//public class Test2 {  //我的实验
//
//    public static void change (int i){
//        i=6;           //给拷贝赋值,并没有改变a指向的值
//    }
//
//    public static void main (String args [ ] ) {
//    int a=5;
//    change(a);
//      System.out.println (a);  //5   JAVA都是传值并且传的都是拷贝的话
//    }
//    }


//public class Test2 {  //我的实验
//
//    public static void change (int i){
//        i++;           //对象是传引用(call by reference),简单类型是传值(call by value)
//                       //传值(call by value)不会改变实际参数的数值
//    }
//
//    public static void main (String args [ ] ) {
//    int a=5;
//    change(a);
//      System.out.println (a);  //5  
//    }
//    }

分享到:
评论

相关推荐

    详解Java的call by value和call by reference

    详解Java的call by value和call by reference Java是一种面向对象的编程语言,它支持两种传递参数的方式:call by value和call by reference。理解这两种方式对于Java开发者来说非常重要,这篇文章将详细解释这两种...

    华为java笔试面试题.pdf

    6. call by value 和 call by reference 的区别是什么?(答:call by value 不会改变实际参数的数值,call by reference 能改变实际参数的容) 7. 在类方法中可以用什么来调用本类的类方法?(答:可以用 this 来...

    java题目[归类].pdf

    变量及其作用域的理解也很关键,例如,call by value和call by reference是两种参数传递方式。call by value不会改变实际参数的值,而call by reference可以改变实际参数的内容,但Java中并没有真正的call by ...

    华为java笔试面试题.doc

    6. 可以用 call by value 和 call by reference 两种方式来传递参数。 7. 在类方法中可以调用本类的类方法,但不能调用实例方法。 多项选择题 1. Java 程序的种类有 Applet、Application 和 Servlet。 2. 环境变量...

    搜狗2010招聘笔试题

    1. **调用方式:call by value 和 call by reference** - **call by value**(值调用):函数调用时,将实参的值复制一份传递给形参。在函数内部对形参的修改不会影响到实参的原始值。 - **call by reference**...

    几个搜狗招聘笔试题,对找工作有帮助。

    Q5: call by value 和 call by reference 的区别? call by value(值传递)是一种参数传递方式,函数调用时,实际参数的值被复制到形式参数中,形式参数的改变不会影响实际参数。而call by reference(引用传递)则...

    09.Dictionary.A.hashing.Call-by-value

    Call-by-value与“Call-by-reference”(引用传递)相对,后者传递的是参数的引用,因此在函数内部对参数的修改会影响到实际参数。 知识点五:词典(Dictionary) 在编程中,词典是一种数据类型,其中的每个元素都...

    C C++之指标 (pointer)参考 (reference) 观念整理与常见问题

    3. call by value, call by address (或 call by pointer), call by reference? - call by value:函数接收的是实参的副本,对副本的修改不会影响到原始变量。 - call by address 或 call by pointer:函数接收的是...

    SAP ABAP Command Reference

    本文章将基于《SAP ABAP Command Reference》这本书的部分内容,深入探讨其中提及的关键知识点,包括ABAP的基础概念、常用命令及其应用场景。 #### 二、为什么使用ABAP? 1. **集成性**:ABAP是专门为SAP系统设计...

    Rhino mocks quick reference

    - **输出参数**:使用 `Expect.Call(dict.TryGetValue("key", out outParam)).OutRef("value").Return(true);` 来处理输出参数。 - **属性获取器**:例如,`Expect.Call(foo.Name).Return("Bob");` 表示期望 `foo....

    CUDA Reference from NVIDIA official site.

    It is important to call this function when no longer using a CUDA context to avoid resource leaks. ##### 1.3 Stream Management RT **1.3.1 cudaStreamCreate** `cudaStreamCreate` creates a new stream...

    C++传值调用与引用调用区别实例代码

    当一个函数被调用时,可以通过不同的方式传递参数,其中最常见的是传值(call by value)和传引用(call by reference)两种方法。这两种方式在内存管理、性能影响以及数据修改能力上有着显著的不同。 #### 1. 传值调用...

    编译原理第七章的答案

    首先,我们来看传值调用(Call by Value)。在给定的程序示例中,当使用传值调用时,实参的副本被传递给形参,形参的改变不会影响实参。因此,在程序(a)的情况下,输出为2,因为实参`a`的值没有受到子程序`p`的...

    findbugs常见Bug以及处理办法

    - **May expose internal representation by incorporating reference to mutable object**:调用set方法,修改对象属性,被修改的对象属性是一个可变的对象。 - **描述**:这通常意味着通过公共接口暴露了内部状态...

    Ruby.Pocket.Reference

    - Explains how to define methods with default argument values, which makes it easier to call methods without specifying all the arguments. This overview provides a detailed look into the key ...

    对C语言函数参数传递的探讨——以交换问题为例.pdf

    例如,在C++中,除了值传递和地址传递(引用传递)外,还有传值引用(Call by Value-Reference)等概念。而现代编程语言如Python或JavaScript则提供了更高级的参数传递机制,如默认参数、关键字参数、不定长参数等,...

    c语言课件 C讲义2010-6-2

    void callByReference(int *x) { ... } int a = 5; callByValue(a); // 不改变a的值 callByReference(&a); // 改变a的值 ``` 7. **指向数组的指针**:一个指针可以指向整个数组,而不是数组的一个元素。例如: ```...

    2022年软考《软件设计师》学习文档手册.pdf

    2022年软考《软件设计师》学习文档...参数传递方法有传值调用(call by value)、引用调用(call by reference)、传名调用(Ca11 by name)和宏扩展(macro expansion)。C语言中的函数,以传值调用方式进展参数传递。

    ABAP PA Topic

    参数传递类型,如按值传递(Call by value)、按值和结果传递(Call by value and result)以及按引用传递(Call by reference),决定了函数调用时数据的处理方式。 ### Event Blocks & Function Modules 事件块(Event ...

Global site tag (gtag.js) - Google Analytics