java传值or传引用 二

(接一)

5. 如何实现类似 swap 的方法

  传值还是传引用的问题,到此已经算是解决了,但是我们仍然不能解决这样一个问题:如果我有两个 int 型的变量 a  b,我想写一个方法来交换它们的值,应该怎么办?

  结论很让人失望——没有办法!因此,我们只能具体情况具体讨论,以经常使用交换方法的排序为例:

/**  6 */

/** *

 @(#) Test.java *

 @author fancy */

public class Test { 

  public static void swap(int[] data, int a, int b) {

       int t = data[a];

        data[a] = data[b];

        data[b] = t; 

  }   

public static void main(String[] args) {

       int[] data = new int[10];

       for (int i = 0; i < 10; i++) {

          data[i] = (int) (Math.random() * 100);            System.out.print(" " + data[i]);   

}     

  System.out.println(); 

      for (int i = 0; i < 9; i++) { 

          for (int j = i; j < 10; j++) { 

              if (data[i] > data[j]) {     

              swap(data, i, j);                }   

        }  

     }

       for (int i = 0; i < 10; i++) {

          System.out.print(" " + data[i]);

       }    

   System.out.println(); 

  }

}

  运行结果(情况之一)

78 69 94 38 95 31 50 97 84 1
1 31 38 50 69 78 84 94 95 97

  swap(int[] data, int a, int b) 方法在内部实际上是改变了 data 所指示的对象的成员数据,即上述讨论的第二种改变参数值的方法。希望大家能够举一反三,使用类似的方法来解决相关问题。

第二种说法

关于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中的参数传递全是以值传递的。

是基本类型,就拷贝一个基本类型传进方法;

是引用,就拷贝一个引用变量传进去方法,

理解了这两点就能理解方法操作对象的相关问题了。最好能画出引用指向对象的图出来,就能完全理解了。
题,调用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)。此时,xy指向了同一个对象。
   x
y指向的是同一个对象, 由于Java的设计,我们可以通过操作引用来达到操作对象的目的。因此,如果我们此时使用y来修改对象的属性 (例如,y.someField++); 你可以看到x指向的对象同时也被修改到了。
   
另一方面,如果我们让y指向另外一个对象, y=new Integer(2); 此时xy就指向了不同的
对象。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]++;              //
修改原来的那个对象
   }
}

 

 

对象是传引用,简单类型是传值,不要被网上的一些概念所迷惑!!!你可以自己做个试验。
至于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 strnew 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:

不会出错的。结果是01

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

总结:对于第一种说法,注意理解“引用是一种数据类型”,对于第二种说法,要理解“参数是引用的一个拷贝” 转自:http://blog.csdn.net/baobeiSimple/archive/2007/08/05/1727053.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值