java变量是值传递,引用传递。
java的变量只有值传递?,传递!,传递!,传递!重要的地方说三遍!!!
我的解释是,不论基本类型变量或是引用类型类型变量,是通过方法形参或者是直接用 “=" 赋值 传递,传递的都是变量的地址。
区别在于,值类型变量的数据是存储在栈中是没有内存地址的,就好比 int= 999 赋值号“=”后面的那个 999,传递的时候就只会复制一份 999 (所以传递的就是值);
而引用类型变量的数据是存储在由jvm在堆中开辟空间里,会在栈中产生内存地址并指向堆中的数据,传递的时候就只会复制栈中的地址(类似0x1234,其本质也是一个值),
综上才说java里变量传递只有值传递。
测试,对象赋值,浅拷贝和深拷贝
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @auther journey&flower
* @data
*/
public class Main {
// 测试对象
static class PeoPle {
public String name;
public int age;
}
//全局变量
static List<String> list = new ArrayList<String>() {{
add("张三");
add("李四");
}};
//全局变量
static PeoPle peoPle = new PeoPle() {{
name = "helloword";
age = 10;
}};
/**
* 深拷贝数据,浅拷贝数据对比
*
* @param referenceObject
*/
static void referenceTransfer(List<String> referenceObject) {
//List<String> list3 = referenceObject;//referenceObject直接赋值给list3默认是浅拷贝,默认只会拷贝栈中的地址
List<String> list3 = JSONArray.parseArray(JSONArray.toJSONString(referenceObject), String.class);//深拷贝,拷贝变量堆中的数据
List<String> list4 = list3;
list3.set(0, "王五");
list4 = new ArrayList<String>() {{//new一个新对象并把新对象在栈中的地址重新赋值给list4,list4和list3的关系就没了
add("888");
add("999");
}};
list4.set(1, "888");
list3 = null;//清除list3的地址,list3变量没有指向地址就会被jvm垃圾回收机制给释放掉.
}
/**
* 测试
*
* @param p
*/
static void test2(PeoPle p) {
PeoPle p1 = p;//浅拷贝,只会拷贝实参对象的栈中内存地址
PeoPle p2 = JSONObject.parseObject(JSONObject.toJSONString(p), PeoPle.class);//深拷贝,拷贝实参对象的堆中数据
}
public static void main(String str[]) throws IOException {
referenceTransfer(list);
test2(peoPle);
}
}
总结:java深拷贝的方式
1、将数据对象序列化成json字符串,再由字符串反序列化成数据对象;
2、通过Java 8 新特性及以上支持stream的filter将数据过滤一遍。