学习内容整理记录,如有错误感谢指正,互相交流,共同进步
摘要
在java方法里面传递的参数,本质是值传递。调用方法时会将参数复制一份并传递到方法里面,对象传递和基础类型传递所造成的不同影响是因为前者是通过引用地址操作对象,后者直接改变引用地址指向对象
方法值传递
1、先举一个普通对象的传递例子
{
User user=new User()
user.setName("jack")
test(user);
System.out.println(user.getName);
}
private void test(User user){
user.setName("jonh");
}
以上方法中的参数对象变化如下
如上图所示
User user1=new User();user.setName("jack")
两行代码后创建 User对象User@0001和栈引用对象user,并对User对象的name属性赋值“jack”
test(user);在调用test方法前,会对参数user进行值复制,此时的user是一个指向User@0001对象地址的引用对象,所以复制之后的user‘本质和user是一样的,指向User@0001对象
在test方法里执行代码user.setName("jonh");这里的逻辑是,先通过user‘找到对象User@0001并修改其属性name的值,整个过程中user、user‘的指向没有变化,所以方法执行完后输出System.out.println(user.getName)的结果为jonh;
2、我们在看普通字符串的的传递
{
String str="123";
System.ont.println(str);
test(str);
System.ont.println(str);
}
private void test(String str){
str="456";
}
执行过程对象变化
重点:在test方法中str‘=“456”,本质上是改变了str'的引用地址,已经和被复制对象str不一样了,且没有对原对象进行修改,可以理解为是一个全新的引用,所以方法执行完后原str打印的值并未发生变化
3、可执行以下代码回顾一下
{
String str=new String("111");
System.out.println(str);//输出111
test1(str);
System.out.println(str);//输出111
}
private void test1(String str){
System.out.println(str); //输出111
str="222";
System.out.println(str);//输出222
}
字符串常量池
constant_pool_table:常量池表,class文件中的所有常量,运行时会复制到runtime_constant_pool
runtime_constant_pool:运行是常量池,存放各种常量对象,每个类都有
string_pool:字符串常量池,存储字符串常量,全局共享,元数据设计思想,
示例1
String abc1=new ("abc");
String abc2=new ("abc");
根据代码执行步骤:
1、检索string_pool发现没有"abc"字符串,在池中创建字符串对象"abc",并在Heap创建
字符串对象"abc",栈中创建引用对象abc1指向堆中的字符串对象"abc"
2、检索string_pool发现有"abc"字符串,直接在Heap创建字符串对象"abc",
栈中创建引用对象abc2指向堆中的字符串对象"abc"
示例2
String abc1=“abc”
String abc2=“abc”
根据代码执行步骤:
1、检索string_pool发现没有"abc"字符串,在池中创建字符串对象"abc",
并在栈中创建引用对象abc1指向池中的字符串对象"abc"
2、检索string_pool发现有"abc"字符串,在栈中创建引用对象abc2指向池中的字符串对象"abc"
示例3
String abc=new (“abc”);
String efg=new (“efg”);
String efg1="efg";
根据代码执行步骤:
1、检索string_pool发现没有abc"字符串,在池中创建字符串对象"abc",并在Heap创建
字符串对象"abc",栈中创建引用对象abc指向堆中的字符串对象"abc"
2、检索string_pool发现没有efg"字符串,在池中创建字符串对象"efg",并在Heap创建
字符串对象"efg",栈中创建引用对象efg指向堆中的字符串对象"efg"
3、检索string_pool发现有"efg"字符串,在栈中创建引用对象efg1指向池中的字符串对象"efg"
示例4
String str1 = "ab";
String str2 = new String("ab");
String str3 = "a" + "b";
String str4 = new String("a") + new String("b");
这里str1、str2、str3和上述情况一致。主要解释一下str4
String str4 = new String(“a”) + new String(“b”)可分解为new String(“a”)和new String(“b”),在执行这两步操作时,都会先去字符串常量池中查找是否存在“a”和“b”,若没有,则在字符串常量池中创建“a”和“b”两个对象,然后再在Heap中创建new String(“a”)和new String(“b”)两个对象。否则直接在Heap中直接创建new String(“a”)和new String(“b”)两个对象。之后会将两个字符串进行拼接,拼接后会再在Heap中创建一个new String(“a”+“b”)对象。
因此若原本字符串常量池中没有“a”“b”,执行String str4 = new String(“a”) + new String(“b”)会创建五个对象,若字符串常量池中已经存在了"a"和"b"则只在Heap中创建三个对象。