Java中,String类型和包装类型作为参数传递时,是属于值传递还是引用传递呢?【转】

原理知识:

如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。如果在函数中改变了副本的 值不会改变原始的值.

如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,而是改变了地址中的 值,那么在函数内的改变会影响到传入的参数。

如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的 地址,所以不会改变参数的值。


String和包装类是什么类型传递这个问题,可能很多人都没有去细想过,下面我就给点我自己的见解。

/**
 * 
 * @author ZHOUMI2
 */

public class Test {

    public static void test1(Integer num){
        num = new Integer(5);
    }

    public static void test2(String str){
        str.replace("1", "4");
    }

    public static void main(String[] args) {

        Integer num = new Integer(1);
        test1(num);
        // 输出结果为1
        System.out.println(num.intValue());

        String str = new String("123");
        test2(str);
        // 输出结果为123
        System.out.println(str);
    }

}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
分析:

    上述程序很容易让人误以为String类型和包装类型是值传递。

其实我们认真想一下:

    String类型和包装类型都是对象类型,所以必然是引用传递。
    但是由于String类和包装类都没有提供value对应的setter方法,我们无法改变其内容,所以导致我们看起来好像是值传递。



    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

以下讨论Integer是引用传递还是值传递


转自:http://www.tuicool.com/articles/AraaQbZ
论integer是地址传递还是值传递

Integer 作为传参的时候是地址传递 , 可以参考如下例子,在程序刚启动的时候把 Integer 的index 对象锁住 ,并且调用了 wait方法,释放了锁的资源,等待notify,最后过了5秒钟,等待testObject 调用notify 方法就继续执行了。大家都知道锁的对象和释放的对象必须是同一个,否则会抛出 java.lang.IllegalMonitorStateException 。由此可以证明 Integer作为参数传递的时候是地址传递,而非值传递。

public class IntegerSyn {

  public static void main(String[] args) throws InterruptedException {
    Integer index = 0;
    TestObject a = new TestObject(index);
    synchronized (index) {
      new Thread(a).start();
      index.wait();
    }
    System.out.println("end");
  }
}

class TestObject implements Runnable {
  private Integer index;

  public TestObject(Integer index){
    this.index = index;
  }

  public void run() {
    try {
      TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    synchronized (index) {
      index.notify();
    }
  }
}

那就会有人问了,为什么执行如下代码的时候两次的输出结果是一样的?

public static void main(String[] args) throws InterruptedException {
    Integer index = 0;
    System.out.println(index);
    test(index);
    System.out.println(index);
  }

  public static void  test(Integer index){
    index++;
  }

理由很简单,可以看到 Integer 类中final的value字段,说明一旦integer类创建之后他的值就不能被修改,在 index++ 的时候Integer是创建一个新的类,所以这个第二次输出的时候结果是一样的!

private final int value;

总结一下java中方法参数的使用情况:

  1. 一个方法不能修改一个基本数据类型的参数(即数值型和布尔型)
  2. 一个方法可以改变一个对象参数的状态
  3. 一个方法不能让对象参数引用一个新的对象

在方法中一个引用指向了一个新的对象,只在方法中生效,出了方法,原来的引用内容是怎么样还是怎么样:
Integer是不可变类,进入一个方法后,在里面的值的改变不会影响方法外的引用

 @Test
    public void testInteger() {
        Integer integer = new Integer(5);
        testchange(integer);
        //输出结果还是5
        System.out.println(integer);
    }

    private void testchange(Integer integer) {
        integer =new Integer(8);
        //这里输出结果是8
        System.out.println("方法里面的integer:"+integer);
    }

原理知识:

如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。如果在函数中改变了副本的 值不会改变原始的值.

如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,而是改变了地址中的 值,那么在函数内的改变会影响到传入的参数。

如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的 地址,所以不会改变参数的值。


String和包装类是什么类型传递这个问题,可能很多人都没有去细想过,下面我就给点我自己的见解。

/**
 * 
 * @author ZHOUMI2
 */

public class Test {

    public static void test1(Integer num){
        num = new Integer(5);
    }

    public static void test2(String str){
        str.replace("1", "4");
    }

    public static void main(String[] args) {

        Integer num = new Integer(1);
        test1(num);
        // 输出结果为1
        System.out.println(num.intValue());

        String str = new String("123");
        test2(str);
        // 输出结果为123
        System.out.println(str);
    }

}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
分析:

    上述程序很容易让人误以为String类型和包装类型是值传递。

其实我们认真想一下:

    String类型和包装类型都是对象类型,所以必然是引用传递。
    但是由于String类和包装类都没有提供value对应的setter方法,我们无法改变其内容,所以导致我们看起来好像是值传递。



  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

猜你喜欢

转载自blog.csdn.net/nakey_xie/article/details/82218321
今日推荐