【JAVA基础】JAVA是值传递还是引用传递
概念
-
指针和引用
首先java中没有指针的概念,但是在c++中是有指针(*)和引用(&)的概念的,不太好区分,但是以swap方法为例的话,两者都可以达到交换的目的。为了更好的区分我先设定
指针:直接指向了数据,所有的修改都是直接对数据的修改(但其实指针也是一个对象,里面的值存放了数据的地址)
引用:通过一个中间引用变量对数据进行了修改,可以通过中间变量间接的修改数据值
-
值传递和引用传递
一直以来我认为的值传递和引用传递都是通过大学课上的swap函数为基础的,所以我认为
值传递:实参和形参无关联,可以类比一个方法中两个变量,只是值一样
引用传递:实参和形参有关联,可以类比一个方法中两个变量指向同一个对象,只是引用名不一样,但是引用值是同一个地址
例子
- 值传递
public class Test {
public static void main(String[] args) {
int val = 20;
Test.test(val);
System.out.println("实参:" + val);
}
private static void test(int val) {
val = 10;
System.out.println("形参:" + val);
}
}
对于基础变量,实参和形参无关联,互补影响,所以输出为
形参:10
实参:20
- 引用传递
public class Test {
public static void main(String[] args) {
Stu stu = new Stu();
stu.setAge(20);
stu.setName("test");
Test.test(stu);
System.out.println("实参:" + stu);
}
private static void test(Stu stu) {
stu.setName("test2");
stu.setAge(10);
System.out.println("形参:" + stu);
}
}
class Stu {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Stu{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Stu是一个对象,因为引用传递的原因,所以形参和实参指向了同一个地址,如果通过形参对数据进行修改,那么实参指向的数据也会发生改变,因为指向了同一个地址,所以输出
形参:Stu{name='test2', age=10}
实参:Stu
- 引用传递
public class Test {
public static void main(String[] args) {
Stu stu = new Stu();
stu.setAge(20);
stu.setName("test");
Test.test(stu);
System.out.println("实参:" + stu);
}
private static void test(Stu stu) {
stu = new Stu();
stu.setName("test2");
stu.setAge(10);
System.out.println("形参:" + stu);
}
}
class Stu {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Stu{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
同样的代码,只是比上面多了一行stu = new Stu();
但此时修改了形参的指向,这里修改的是形参,并未对数据进行修改,修改完后的形参指向了新的地址,从而与实参关联断开,所以结果为
形参:Stu{name='test2', age=10}
实参:Stu
- 引用传递
public class Test {
public static void main(String[] args) {
String val = "20";
Test.test(val);
System.out.println("实参:" + val);
}
private static void test(String val) {
val = "10";
System.out.println("形参:" + val);
}
}
对于String这个对象,因为是被final修饰的,所以不管任何改变了数据的操作都是在String池子里新建一个,这里因为没有用new,所以都是指向的String常量池,而且一个指向了"10",一个指向了“20”
结论
从上面的3和4的例子我们看到如果在方法中对引用类型的形参进行了“=”这个操作,那么与实参就脱离了连接,形参就不会发生任何改变,所以要注意。
所以我的结论就是基本类型值传递,对象类型引用传递。我在网上看到很多说是值传递,其实说的也有道理,但是每个人有自己的理解,能解决生产中的问题就行。