Java是值传递还是引用传递

先给出答案:

Java是值传递

参考链接:Java中是值传递和引用传递_java 是值传递,还是引用传递-CSDN博客

String 为什么不可变?

当传的是基本类型时,传的是值的拷贝,对拷贝变量的修改不影响原变量;

当传的是引用类型时,传的是引用地址的拷贝,但是拷贝的地址和真实地址指向的都是同一个真实数据,因此可以修改原变量中的值;

当传的是String类型时,虽然拷贝的也是引用地址,指向的是同一个数据,但是String的值不能被修改,因此无法修改原变量中的值。(后面说一下String为什么不可变)

当传的是数组时,传的是数组地址的拷贝,和上述的引用类型一样,都同一个数据。

思考原因:在做leetcode226翻转二叉树时突然把swap函数写成

swap(node.left,node.right);

public void swap(TreeNode left,TreeNode right){
    TreeNode temp = left;
    left = right;
    right = temp;
}			//并不能改变外面的A B

这样是不能改变node节点的左右值的。类似下图:(图来自参考链接)

 

并不能改变A和B真正的指向

把函数改成

swap(node);

public void swap(TreeNode root){
    TreeNode temp = root.left;
    root.left = root.right;
    root.right = temp;
}			//复制引用链接,和对象本身都指向堆,所以可以改变

有同学问,这不一样吗?

不一样的

第一个示例中虽然我们传递的是leftright对象的引用的副本,但在swap方法中对leftright的重新赋值并不会影响原始的node对象中的leftright属性。这是因为在Java中,方法参数是按值传递的,对于对象类型的参数,传递的是对象引用的副本。

当我们调用swap(node.left, node.right)时,实际上是将node.leftnode.right的引用传递给了leftright,而在swap方法中对leftright的重新赋值只会影响方法内部的变量,不会影响原始的node对象。(修改的是局部变量left和right而不是node.left和node.right

如果想要在方法中交换node对象的leftright属性,可以使用数组、集合或自定义对象等方式传递,或者通过返回值的方式来实现。这样可以在方法内部修改对象的属性,从而实现交换对象的目的。

在第二个示例中,swap方法接受一个TreeNode对象作为参数,然后在方法内部直接修改了node对象的属性,实现了node.leftnode.right的值的交换。这种方式会影响原始的node.leftnode.right的值,因为传递的是对象的引用,对对象属性的修改会影响原始对象。(修改的是node的属性)

完整层序遍历代码

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null) return null;
        Deque<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            for(int i=0;i<size;i++){
                TreeNode node = queue.poll();
                swap(node);
                if(node.left!=null) queue.add(node.left);
                if(node.right!=null) queue.add(node.right);
                
            }
        }
        return root;
    }
    public void swap(TreeNode root){
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
    }
}

String 为什么不可变?

先看一下String的源码

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
}

String内部是char型的数组,由final修饰,值不能被修改。

String类内部所有的字段都是被private修饰。而且String没有对外提供修改内部状态的方法,因此value数组不能改变。

所以,String是不可变的。

那String不可变有什么好处吗?(参考GPT的回答)

  1. 线程安全:由于String是不可变的,多个线程可以同时访问同一个String对象而无需担心数据被修改,从而提高了线程安全性。
  2. 缓存Hash值:由于String的不可变性,可以缓存String的hash值,HashMap通常使用Integer或者String作为Key,这样就不用重复计算hash值,提高了字符串的hash性能。
  3. 字符串池:由于String的不可变性,Java中的字符串池可以被实现,相同的字符串常量在内存中只有一份拷贝,节省了内存空间。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值