首页 > 编程语言 >Java求值策略

Java求值策略

时间:2023-01-03 21:22:27浏览次数:42  
标签:Java 策略 传递 test 参数 引用 类型 求值

为什么说Java不存在引用传递?

在Java语言中,存在两种数据类型,一种是基本类型,如int、byte等8种基本类型,一种是引用类型,如String、Integer等。这两种数据类型区别就在于,基本类型的各个类型大小是固定的,如int类型占4个字节,且数据存储于栈中;而引用类型大小则不固定,根据引用类型的属性构成决定的,且数据存储是在堆中,栈中的变量存储是指向堆中的数据引用;


正是因为有两种数据的存储区别,很多人才容易将值传递和引用传递搞混了。并且容易产生误解,Java数据如果是基本类型就是值传递,如果是对象(引用类型)那就是引用传递,但这是错误的!

值传递和引用传递

在程序语言中是这样定义值传递和引用传递的:

值传递:是在调用函数时将实际参数复制一份到函数中,这样如果对参数进行修改,将不会影响到实际的参数。

引用传递:是指在调用函数时将实际参数地址直接传递到函数中,那么如果函数中对参数进行修改,将影响到实际的参数。

对于上述概念是程序语言中对于值传递和引用传递的通用概念,那我们用代码来验证一下为何说Java是不存在引用传递的。

首先看基本类型的传递

这段代码最后输出是:

这个结果是毫无疑问的,分别输出的pvb是100和1!即使调用了passByValue(int pbV),在方法中改变了pbV的值,但是在main方法中的pbV的值仍然是1,这说明传入passByValue方法的是个拷贝的副本值,在方法中对这个副本值进行修改,不会影响到原变量,证实Java基本类型是值传递

再换成引用类型的看看:

大家猜猜最后会输出什么......如果按照值传递的理论概念,传递给函数的变量应该是拷贝的副本,无论在方法函数中做出什么样的修改,都不会影响到原值,所以按照值传递是不是应该输出两个“Java”字符串?!

但事实上最后输出结果却是“Java”和“Java+python”两个字符串:

难道Java是存在引用传递的?

答案是不存在的!我们来分析上面的程序在内存中的存储:

首先在main方法中创建一个StringBuffter对象,此时buffter变量引用此对象的地址,然后调用passByReference方法,此时,将buffter变量引用的地址拷贝一份副本传入passByReference方法,在passByReference中调用引用对象的append(“+python”)方法,此对象变成了”Java+python”字符串,最后输出main方法输出buffer变量所指向的对象,即”Java+python”字符串;

话说回来,将引用拷贝一份副本传至方法参数中,难道这不算引用传递吗?当然不算!

我们再来读一下引用传递的概念定义:引用传递是指在调用函数时将实际参数地址直接传递到函数中,那么如果函数中对参数进行修改,将影响到实际的参数

事实上,在Java语言中,我们是不能直接获取到实际参数的地址的,我们所使用的都是引用去操作其指向的地址的对象,引用≠实际参数地址,所以在Java语言中不存在引用传递。只是因为在传递引用类型的对象时,拷贝对应的引用值副本进行传参,很多人误以为这就是引用传递,但这其实是值传递。

结论

在Java语言中无论是基本数据类型还是引用类型,都是使用值传递的方式,对于引用传递来说是不存在的。

那最后上一个“硬菜”,下面的这段代码为什么会输出两个一模一样的"Java"字符串呢!如果了解String类型底层的朋友,答案一眼就能看出了,欢迎评论留言。

public class MemberServiceImpl{
void test (int i){
        i=3;
    }
    void testObj (Test test){
        test=new Test();
        System.out.println(test.getI());
    }
    public static void main(String[] args) {
        MemberServiceImpl memberService=new MemberServiceImpl();
        int i=0;
        memberService.test(i);
        System.out.println("i:"+i);

        Test test=new Test();
        test.setI(111);
        memberService.testObj(test);
        System.out.println(test.getI());
    }
}

运行结果:
i:0
null
111(之所以不是null是因为,testObj方法内外的引用不是同一个,如果不修改引用指向的对象,则操作的是同一个对象)

标签:Java,策略,传递,test,参数,引用,类型,求值
From: https://www.cnblogs.com/LoveShare/p/17023405.html

相关文章

  • 第二十章《Java Swing》第3节:布局管理器
    ​当把组件添加到窗体上时,并不是直接把组件添加到JFrame对象上的,而是需要先获得窗体的内容面板,然后把组件添加到内容面板上。获得内容面板的方式是调用窗体的getContentPane......
  • 黑马程序员Javaweb综合案例错误总结整理
    案例整理(呕心沥血的教训)其他的我大部分还是不知道那里出了问了,我这个新建的项目must3终于成功了那个品牌名称和企业名称没有,是要在BrandMapper里加注解@ResultMap......
  • 第二十章《Java Swing》第4节:事件处理与监听器
    ​当程序员向窗体上添加了按钮等组件之后就能够操作这些组件,但在20.3小节的各个案例中,虽然在窗体上添加了一些按钮,但点击这些按钮并没有任何反应,因此这些按钮也就成了毫无意......
  • [MySQL] 索引的使用、SQL语句优化策略
    目录索引什么是索引索引的创建与删除创建索引删除索引索引的使用使用explain分析SQL语句最佳左前缀索引覆盖避免对索引列进行额外运算SQL语句优化小表驱动大表索引什么是......
  • JavaScript条件语句
    JavaScript条件语句之break1<!DOCTYPEhtml>2<html>3<head>4<metacharset="utf-8">5<title>JavaScriptbreak语句啊</title>6......
  • Java【使用HashMap类实例化一个Map类型的对象】
    题目:使用HashMap类实例化一个Map类型的对象m1,键(String类型)和值(int型)分别用于存储员工的姓名和工资,存入数据如下:张三——800元;李四——1500元;王五——3000元;将张三的工......
  • Java线程同步总结
    线程同步的关键是保证临界资源访问的原子性和可见性。一般的解决方案是使用volatile(保证可见性、不一定保证原子性)修饰共享变量,或是加锁(直接保证原子性和可见性)进行线程同......
  • Java【封装一个新闻类,包含标题和内容属性】
    题目:1、封装一个新闻类,包含标题和内容属性,提供get、set方法,重写toString方法,打印对象时只打印标题;(10分)2、只提供一个带参数的构造器,实例化对象时,只初始化标题;并且实例化......
  • JavaScript 的数据是如何回收的
    因为数据是存储在栈和堆两种内存空间中的,所以接下来我们就来分别介绍“栈中的垃圾数据”和“堆中的垃圾数据”是如何回收的。调用栈中的数据是如何回收的当一个函数执行......
  • argocd 同步策略--忽略某个配置同步
    背景当我在k8s中用cronhpa+hpa实现定时pod扩容的同时还能兼容平时的hpa弹性伸缩。cronhpa通过修改hpa的minReplicas与maxReplicas,从而实现pod的伸缩。但是,当hpa......