Java学习总结(二)

Java传参时是引用传递还是值传递,有说Java中只有值传递,也有些地方说引用传递和值传递都存在,本篇记录思考过程,不保证正确性, 感兴趣的同学一起讨论。

Java中数据类型分为两大类,基本类型和对象类型

首先搞清楚 基本类型 和 引用类型的不同之处


int num = 10;
String str = "hello";


如图所示,num是基本类型,值就直接保存在变量中,它代表的值就是数值本身。

而str是引用类型,变量中保存的只是实际对象的地址,而不是对象本身。一般称这种变量为"引用",引用指向实际对象,实际对象中保存着内容。

对象本身存放在这个引用值所表示的地址的位置。

基本类型包括整数、浮点数、字符是基本类型 (byte,short,int,long,char,float,double,Boolean,returnAddress),

引用类型包括字符串、数组是引用类型(内存数据的索引)


引用传递和值传递

这里要用实际参数和形式参数的概念来帮助理解,

值传递:

方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数后面方法中的操作都是对形参这个值的修改,不影响实际参数的值

引用传递:

也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址;
在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象

下面举个例子来帮助理解:

public class Test {

    public static void main(String[] args) {
        // 第一种情况传入数组到方法
        int[] a = { 1, 2, 3 };
        aaa(a,0);
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
        // 第二种情况传入字符串
        String b = "bbb";
        bbb(b);
		System.out.println(b);
		
		// 第三种情况传入整型
        int c = 111;
        ccc(c);
		System.out.println(c);
    }
    public static void aaa(int[] arr, int x){
        arr[0] = x;
    }
    public static void bbb(String x) {
        x = "zzz";
    }
    public static void ccc(int x) {
        x = 222;
    }
}


输出结果是:

0
2
3
bbb
111

第一种情况很好判断,数组的参数传递是引用传递,将内存地址传递到aaa方法,将堆中的arr[0]重新赋值为0。

第二种情况,虽然字符串的参数传递方式是引用传递,但是bbb方法种赋值运算符会改变引用中所保存的地址,即bbb方法中的字符串x的内存地址会被覆盖但是原来的对象不会被改变,这就是所谓的string不变性。

第三种情况,整型是基本类型,参数传递方式是值传递,将整型c的值赋给方法ccc种的变量x,但是主方法重的c的值没有变化,所以输出的还是111。


String有不变性

String的特点:一旦被赋值,则不能被改变



面试题

String s = new String("Hello")与String s = "hello"的区别?

== 比较的是引用类型,是地址值是否相同
equals 比较的是引用类型,默认是比较地址值,而String类重写了equals方法,比较的是内容是否相同。

public class StringDemo3 {
    public static void main(String[] args) {
    	String s1 =new String("Hello"); //常量池、堆中各新建一个对象,但内存地址不一样
    	String s2 = "Hello"; //常量池对象已创建,地址指向s1的常量池地址引用
    	System.out.println(s1==s2);   //false
    	System.out.println(s1.equals(s2)); //true
   }
}



结论

1、基本类型参数的传递,是调用方值的复制。双方各自的后续修改,互不影响。

2、引用类型参数的传递,调用方的变量和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方。

那么3个例子中,

  1. 整数的参数传递理解了,复制出来的,分家了,自己管理自己的,类读出数据不变。
  2. 字符串数组的参数传递也理解了,都是指向同一个地方,数组的一个元素改了,类读出数据也就变了(类一直指向这里)。
  3. 字符串也是引用参数,为什么类读出数据不变?因为重写了整个字符串(新开内存和指向,参看字符串更改章节),类依然指向之前内存块,类读出数据不变,同结论1。如果只是修改字符串内存中某一个字符的值,则同结论2。

简单总结:类对基本类型是复制数据本身,新开内存。对引用类型是复制指向地址,内存数据本身变化了,类读出数据跟着变化。但字符串修改,是新开内存新指向,已经不能影响类数据。

参考文献:

Java 到底是值传递还是引用传递

Java—初学—String的特点:一旦被赋值,则不能被改变

1000

GS

北京 | php攻城狮

创作 35 粉丝 2

fighting