首页 > 编程语言 >深入理解Java引用类型

深入理解Java引用类型

时间:2024-01-31 13:44:07浏览次数:25  
标签:Java 对象 传递 int 深入 引用 类型

深入理解Java引用类型

  在Java中类型可分为两大类:值类型与引用类型。值类型就是基本数据类型(如int ,double 等),而引用类型,是指除了基本的变量类型之外的所有类型(如通过 class 定义的类型)。所有的类型在内存中都会分配一定的存储空间(形参在使用的时候也会分配存储空间,方法调用完成之后,这块存储空间自动消失), 基本的变量类型只有一块存储空间(分配在stack中), 而引用类型有两块存储空间(一块在stack中,一块在heap中),在函数调用时Java是传值还是传引用,这个估计很多人至今都很糊涂,下面用图形与代码来解释:

 

  在上图中引用类型在传参时不是在heap中再分配一块内存来存变量c 所指向的A(),而是让a 指向同一个A 的实例,这就与C++ 中的指针一样,先声明指针变量a,b,c,d 在传参的时候让a 指向c所指向的内存,让 d 指向 b 所指向的内存。很明显Java中的引用与C++中的指针在原理上是相类似的,但记住Java没有指针,只有引用。下面再通过一些具体的代码来讨论引用:

 

1. 简单类型是按值传递的

Java 方法的参数是简单类型的时候,是按值传递的 (pass by value)。这一点我们可以通过一个简单的例子来说明:

package test;

 

public class Test {

   //交换两个变量的值

   public static void Swap(int a,int b){

      int c=a;

      a=b;

      b=c;

      System.out.println("a: "+a);

      System.out.println("b: "+b);

   }

  

   public static void main(String[] args){

      int c=10;

      int d=20;

      Swap(c,d);

      System.out.println("After Swap:");

      System.out.println("c: "+d);

      System.out.println("d: "+c);

   }

}

运行结果:

a: 20

b: 10

After Swap:

c: 20

d: 10

  不难看出,虽然在 Swap (a,b) 方法中改变了传进来的参数的值,但对这个参数源变量本身并没有影响,即对 main(String[]) 方法里的 a,b 变量没有影响。那说明,参数类型是简单类型的时候,是按值传递的。以参数形式传递简单类型的变量时,实际上是将参数的值作了一个拷贝传进方法函数的,那么在方法函数里再怎么改变其值,其结果都是只改变了拷贝的值,而不是源值。

 

2. 什么是引用

  Java 是传值还是传引用,问题主要出在对象的传递上,因为 Java 中简单类型没有引用。既然争论中提到了引用这个东西,为了搞清楚这个问题,我们必须要知道引用是什么。

  简单的说,引用其实就像是一个对象的名字或者别名 (alias),一个对象在内存中会请求一块空间来保存数据,根据对象的大小,它可能需要占用的空间大小也不等。访问对象的时候,我们不会直接是访问对象在内存中的数据,而是通过引用去访问。引用也是一种数据类型,我们可以把它想象为类似 C++ 语言中指针的东西,它指示了对象在内存中的地址——只不过我们不能够观察到这个地址究竟是什么。

如果我们定义了不止一个引用指向同一个对象,那么这些引用是不相同的,因为引用也是一种数据类型,需要一定的内存空间(stack,栈空间)来保存。但是它们的值是相同的,都指示同一个对象在内存(heap,堆空间)的中位置。比如:

      String a="This is a Text!";

      String b=a;

 

  通过上面的代码和图形示例不难看出,a 和 b 是不同的两个引用,我们使用了两个定义语句来定义它们。但它们的值是一样的,都指向同一个对象 "This is a Text!"。但要注意String 对象的值本身是不可更改的 (像 b = "World"; b = a; 这种情况不是改变了 "World" 这一对象的值,而是改变了它的引用 b 的值使之指向了另一个 String 对象 a)

 

  如图,开始b 的值为绿线所指向的“Word Two”,然后 b=a; 使 b 指向了红线所指向的”Word“.

 

这里我描述了两个要点:

(1) 引用是一种数据类型(保存在stack中),保存了对象在内存(heap,堆空间)中的地址,这种类型即不是我们平时所说的简单数据类型也不是类实例(对象);

(2) 不同的引用可能指向同一个对象,换句话说,一个对象可以有多个引用,即该类类型的变量。

 

3. 对象是如何传递的呢

  随着学习的深入,你也许会对对象的传递方式产生疑问,即对象究竟是“按值传递”还是“按引用传递”?

(1)认为是“按值传递”的:

package test;

 

public class Test {

      public static void Sample(int a){

         a+=20;

         System.out.println("a: "+a);

      }

     

      public static void main(String[] args){

         int b=10;

         Sample(b);

         System.out.println("b: "+b);

   }

}

运行结果:

a: 30

b: 10

    在这段代码里,修改变量 a 的值,不改变变量 b 的值,所以它是“值传递”。

(2)认为是“按引用传递”的:

package test;

 

public class Test {

      public static void Sample(StringBuffer a){

         a.append(" Changed ");

         System.out.println("a: "+a);

      }

     

      public static void main(String[] args){

         StringBuffer b=new StringBuffer("This is a test!");

         Sample(b);

         System.out.println("b: "+b);

   }

}

运行结果:

a: This is a test! Changed

b: This is a test! Changed

  在Sample(StringBuffer)这个函数中,修改了引用 a 的值,同时 b 的值也变化了,所以它是“按引用传递”的!

  那么对象(记住在Java中一切皆对象,无论是int a;还是String a;,这两个变量a都是对象)在传递的时候究竟是按什么方式传递的呢?其答案就只能是:即是按值传递也是按引用传递,但通常基本数据类型(如int,double等)我们认为其是“值传递”,而自定义数据类型(class)我们认为其是“引用传递”。

标签:Java,对象,传递,int,深入,引用,类型
From: https://www.cnblogs.com/JavaYuYin/p/17999093

相关文章

  • 深入浅出堆排序: 高效算法背后的原理与性能
    ......
  • 阿里云推出 3.x Java 探针,解锁应用观测与治理的全新姿势
    作者:张铭辉、泮圣伟前言随着春节大促即将到来,为了确保线上业务高效稳定地运行,电商企业大多会对旗下关键业务应用进行多轮测试。通过模拟线上较高流量的请求,来观察服务性能的实际表现。以某企业的业务测试报告举例:图1压测报告显示,成功率非常低,且全局接口成功率都很低通过报......
  • 深入了解java对象分配
    1.对象的创建在语言层面上,创建对象通常仅仅是一个new关键字而已,而在虚拟机中,对象(对象限于普通Java对象,不包括数组和Class对象等)的创建又是怎样一个过程呢?当Java虚拟机遇到一条字节码new指令时,①首先将去检査这个指令的参数是否能在常量池中定位到一个类的符号引用,并且......
  • Java:JetBrains系列IDEA使用Git很慢(任何git操作都很慢)
    问题说明公司电脑上使用IntelliJIDEA的时候发现操作Git特别的慢,status、fetch、pull、checkout、commit这些基础操作都特别特别慢!!!!!让人爆发的是在Settings里面查Git的版本需要20多秒!!!!!!(有时候真的想砸电脑……)解决办法这里查了好久的博文,几乎都是说commit屏蔽TODO检查的文章......
  • Java21 + SpringBoot3整合springdoc-openapi,自动生成在线接口文档,支持SpringSecurity
    目录前言相关技术简介OpenAPISwaggerSpringfoxspringdocswagger2与swagger3常用注解对比实现步骤引入maven依赖修改配置文件设置api-docs和swagger-ui访问权限定义springdoc配置类修改Controller类和实体类查看效果总结前言近日心血来潮想做一个开源项目,目标是做一款可以适配多......
  • 深入浅出Java多线程(四):线程状态
    引言大家好,我是你们的老伙计秀才!今天带来的是[深入浅出Java多线程]系列的第四篇内容:线程状态。大家觉得有用请点赞,喜欢请关注!秀才在此谢过大家了!!!在现代软件开发中,多线程编程已经成为提升应用程序性能和响应能力的关键技术。Java作为一门支持多线程编程的主流语言,其内置的丰富并......
  • jQuery引用教程,CDN或下载教程
    如何在网页中添加jQuery?jQuery库是一个JavaScript文件,可以使用HTML的<script>标签引用它,通过其他云厂商提供的CDN在网页中添加jQuery。阿腾云atengyun.com分享多种安装jQuery的方法:下载jQuery并引用jQuery有两个版本的可供下载:Productionversion–用于实际的网站中,已被精简和......
  • 什么是JavaScript表达式语句?
    JavaScript语法(三):什么是表达式语句?不知道你有没有注意到,我们在语句部分,讲到了很多种语句类型,但是,其实最终产生执行效果的语句不多。事实上,真正能干活的就只有表达式语句,其它语句的作用都是产生各种结构,来控制表达式语句执行,或者改变表达式语句的意义。今天的课程,我们就深入到......
  • Java:Gradle安装与配置教程
    下载Gradle工具下载地址:Gradel官网gradle手动安装时,须先安装 jdk1.8 或以上版本安装Gradle工具解压并配置文件解压刚才下载的压缩包创建下载源的配置文件allprojects{repositories{mavenLocal()maven{name"Alibaba";url"https://m......
  • 深入解析CompletableFuture的功能和用法
    https://zhuanlan.zhihu.com/p/650390185?utm_id=01.CompletableFuture简介1.1概述CompletableFuture是Java8中引入的一个类,它实现了CompletionStage接口,提供了一组丰富的方法来处理异步操作和多个任务的结果。它支持链式操作,可以方便地处理任务的依赖关系和结果转换......