String 类型的参数,传值还是传引用?

本文详细解析 Java 中 String 类型的引用机制与常量池原理,通过实例演示 String 对象的不可变性及引用传递过程,帮助理解 Java 中 String 对象的内存分配与生命周期。

 

public static void main(String[] args) throws Exception {  
        String str="aaaaaaaa";  
        change(str);  
        System.out.println(str);  
    }  
  
    public static void change(String str){  
        str="bbbbbbb";  
    }  

 结果是aaaaa,而不是改变过的bbbbb.

 

解释:

对象是传引用(准确说应该是指针,Java 中没有C 意义上的引用),但是如果引用的是个String对象,情况就不同,因为String 一旦创建就不能改变,这才是关键(本质)。

在change 方法中给该方法的局部变量str 重新赋值时,因为str 指向的位置是String 常量池,是不能改变的,所以只能产生一个新的String 对象,change 方法中的str 指向新的对象,而main 方法中的str 变量还是指向之前产生的对象。

 

这跟一般的传引用是不一样的,因为一般的引用可以改变其指向的地址上的对象值,所以传来传去如果大家还是指向同一个地址,一改全部都改变了。

可以用StringBuffer 试试,结果和你预期的就会一致。如下面的代码

 

public static void main(String[] args) throws Exception {  
    StringBuffer str=new StringBuffer("aaaaaaaa");  
    change(str);  
    System.out.println(str);  
}  
  
public static void change(StringBuffer str){  
    str=str.replace(0, str.length(), "bbbbbbbb");  
}  

  也就是说,如果修改了引用指向的地址的内容,所有指向该地址的引用都会受到影响,这才是传引用的根本所在。

使用String s="" 的方式产生的String 对象会被放入String 常量池中,而String 常量池中相同的String 对象只会有一个Copy ,故,public static void main(String[] args) throws Exception {  

    String str1="aaaaaaaa";  
    String str2="aaaaaaaa";  
    System.out.println(str1==str2);  
}  

  将输出true. 而使用new String 产生的对象就跟一般的对象一样,会在普通的Heap 中,此对象会同时被加入String常量池(不是很好验证),

 

public static void main(String[] args) throws Exception {  
    String str1=new String("aaaaaaaa");  
    String str2=new String("aaaaaaaa");  
    System.out.println(str1==str2);  
} 

 将输出false.

 

Java中,参数递机制始终是**递**(Pass by Value),这一点是理解Java方法调用行为的关键。无论递的是基本数据类型还是对象引用Java总是通过复制实际参数来完成参数递。 对于基本数据类型(如`int`、`float`等),递的是变量所存储的实际的副本。因此,在方法内部对形参的修改不会影响原始变量[^4]。 例如: ```java public class ValuePass { public static void main(String[] args) { int num = 10; System.out.println("改之前的:" + num); // 输出 10 modify(num); System.out.println("改之后的:" + num); // 输出仍然是 10 } private static void modify(int num2) { num2 = 11; } } ``` 对于对象类型(如类实例),递的是对象引用的副本,而不是对象本身。这意味着如果方法内部更改了对象的状态(例如修改对象的属性),这些更改会影响原始对象;但如果在方法内部将形参指向一个新的对象,则原始对象不受影响[^1]。 例如: ```java class Person { String name; public Person(String name) { this.name = name; } } public class ReferenceExample { public static void main(String[] args) { Person p = new Person("Alice"); System.out.println(p.name); // 输出 Alice changePerson(p); System.out.println(p.name); // 输出 Bob } public static void changePerson(Person person) { person.name = "Bob"; person = new Person("Charlie"); // 此更改不影响原始引用 } } ``` 综上所述,Java只支持递。对于对象而言,虽然递的是引用的副本,但这并不等同于“引用递”这一术语通常所指的行为(如C++中的引用递)[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值