一、 概述
在编写Java代码时候,对于一个内部或者外部函数的调用,我们总是通过入参和返回值的方式进行数据交换和流转。有时候,我们传递的入参会本身被其他方法修改,有时候我们不得不通过返回值得方式传递处理的结果。那么这里我们就学习一下,具体何时入参会被调用方法修改,何时入参不会被调用的方法所修改。
二、 结论写在前面
为了便于阅读,把经过测试推演得到的结论写在前面,具体的推演在第三小节。
- Java中的方法是传值的
- 对于引用型对象,传递的是引用的值
- 在方法中对值的修改无效,因为修改的是值得拷贝
- 在方法中对引用指向的对象的修改是有效的,因为该地址内存储的对象发生了变化
三、 代码推演写在后面
下面我们就通过代码,来验证一下在方法的调用中,传递的到底是值还是引用,在方法中的修改会对入参产生怎样的作用。
测试程序
/**
* Created by ryan01.peng on 2017/6/21.
*/
public class LeCallByValue {
public static void main(String[] args) {
ToBeCalled toBeCalled = new ToBeCalled();
int a = 1;
String name = "唯品会开发指南";
System.out.println("调用函数前:"+a);
toBeCalled.passValue(a); // 传值,在方法中对值的修改不会影响,原来的值。
System.out.println("调用函数后:"+a);
Book book = new Book();
book.setId(a);
book.setName(name);
System.out.println("book调用函数前:"+book);
toBeCalled.passPointer1(book); //传递的是引用的值,在方法中对值的修改是对拷贝的修改,不会影响原来的值,所以这个引用还是指向原来的对象
System.out.println("book调用函数后:"+book);
Book book2 = new Book();
book2.setId(a);
book2.setName(name);
System.out.println("book2调用函数前:"+book2);
toBeCalled.passPointer2(book2); 这里我们没有用返回值对book进行赋值,book同样发生了改变,是因为引用指向的对象发生修改。
System.out.println("book2调用函数后:"+book2);
toBeCalled.testString(name);
System.out.println("调用函数后:"+name); //传递引用的值,这里没有发生改变
System.out.println("--------------------------------一下学习== 和equals----------------------------------------------");
int b = 1;
int c = 1;
Integer d = 1;
Integer e = 1;
Integer f = new Integer(1);
Integer g = new Integer(1);
String s1 ="yyyy";
String s2 ="yyyy";
String s3 = new String("yyyy");
String s4 = new String("yyyy");
String s5 = new String(s1);
System.out.println("b==c");
System.out.println(b==c); //基础类型之间的 == 比较的是值
System.out.println("d == e");
System.out.println(d == e); //这里虽然是包装类型的引用,但是赋值时候指向基础类型,所以其d和e的作为引用其值是相等的
System.out.println("b == e");
System.out.println(b == e); // 拆箱,比较值
System.out.println("d.equals(e)");
System.out.println(d.equals(e)); //比较的是值 ,下同
System.out.println("d.equals(a)");
System.out.println(d.equals(a));
System.out.println("b==f");
System.out.println(b==f); // 比较值
System.out.println("d==f");
System.out.println(d==f); //比较值
System.out.println("f==g");
System.out.println(f==g); // f和g分别指向了不同对象,f和g的值不同,但其指向的两个对象equals
System.out.println("d.equals(f)");
System.out.println(d.equals(f));
System.out.println("f.equals(g)");
System.out.println(f.equals(g));
System.out.println("s1==s2");
System.out.println(s1==s2); // 引用S1/s2指向同一个对象。
System.out.println("s1==s3");
System.out.println(s1==s3); // s3是new出来的,在堆中分配内存,故指向不同
System.out.println("s1==s5");
System.out.println(s1==s5); // 引用类型,指向不同
System.out.println("s1.equals(s2)"); // 以下均为true,equals比较的是字符串的内容
System.out.println(s1.equals(s2));
System.out.println("s1.equals(s3)");
System.out.println(s1.equals(s3));
System.out.println("s3.equals(s4)");
System.out.println(s3.equals(s4));
System.out.println("s3.equals(s5)");
System.out.println(s3.equals(s5));
}
}
被调用方法封装在这个类中
/**
* Created by ryan01.peng on 2017/6/21.
*/
public class ToBeCalled {
public String passValue(int a){
a=a+1;
return "processed:"+a;
}
public String passPointer1(Book book){
Book resultBook = new Book();
resultBook.setId(book.getId()+1);
resultBook.setName("processed"+book.getName());
book = resultBook;
return "succsess";
}
public String passPointer2(Book book){
book.setId(book.getId()+1);
book.setName("processed"+book.getName());
return "succsess";
}
public void testString(String s){
s = "春江花月夜";
}
}
演示代码中用到的实体类
/**
* Created by ryan01.peng on 2017/6/21.
*/
public class Book {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
输出内容:
com.vip.vcp.ryan.zhaunzheng.leBasic.LeCallByValue
调用函数前:1
调用函数后:1
book调用函数前:Book{id=1, name='唯品会开发指南'}
book调用函数后:Book{id=1, name='唯品会开发指南'}
book2调用函数前:Book{id=1, name='唯品会开发指南'}
book2调用函数后:Book{id=2, name='processed唯品会开发指南'}
调用函数后:唯品会开发指南
--------------------------------一下学习== 和equals----------------------------------------------
b==c
true
d == e
true
b == e
true
d.equals(e)
true
d.equals(a)
true
b==f
true
d==f
false
f==g
false
d.equals(f)
true
f.equals(g)
true
s1==s2
true
s1==s3
false
s1==s5
false
s1.equals(s2)
true
s1.equals(s3)
true
s3.equals(s4)
true
s3.equals(s5)
true
Process finished with exit code 0