Java细节:深入了解引用类型

简介: Java细节:深入了解引用类型

我们知道在Java中类型可分为两大类:基本类型与引用类型。


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

20190219201925656.png

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


一、基本类型是按值传递的


当Java 方法的参数是基本类型的时候,是按值传递的。我们上代码说明:

public static void main (String[] args) {
    int a = 99;
    int num = 100;
    Integer NUM = 101;
    change0(num);
    change0(a);
    change0(NUM);
    System.out.println(num);
    System.out.println(NUM);
    System.out.println(a);
  }
  public static void change0(int a) { 
    a = 1;
    System.out.println(a);
  }
  public static void change0(Integer a) { 
    a = 12;
  } 

运行结果:

1

100

101

99


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


下面再用代码看一下:

public class Loop {
  public String name;
}
    Loop a = new Loop();
    Loop b = a;
    a.name = "123";
    b.name = "345";
    //a给name赋值123,后来b使name变为了345,a也会受影响改变值
    System.out.println(a.name);
    //a = null;使得a指向断开,不影响b,若改为a。name则b受影响
    a = null;
    System.out.println(b.name);
    //前面使得a = null;断开了a的指向,使a在堆中没有初始空间了,无法存放123,会报错
    a.name = "123";
    System.out.println(a.name);

运行结果:


20190219212350620.png

二、引用类型


首先我们要知道,引用类型的出现是为了节省内存,当我们使用引用类型时,一定要给定一个空间,
即需要new一个对象。


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

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

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

 String a="This is a Text!";
 String b=a;

20190219210713897.png


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

20190219211116903.png


如图,开始b 的值为所指向的“word1”,然后 b=a; 使 b 指向了蓝线所指向的”word“。


这里我描述了两个要点:

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

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


三、对象是如何传递的呢


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


  下面我们看代码:


  public static void main(String[] args) {
    Te aa = new Te();
    aa.name = "100";
    Te bb = new Te();
    bb.name = "55";
    change2(aa,bb);   
    System.out.println(aa.name);//bbb  qqqq
    System.out.println(bb.name);// bbb       qqqq
  }
  public static void change2(Te a,Te aa) {    
    Te temp = new Te();
    temp.name = a.name;
    a.name = aa.name;
    aa.name = temp.name;    
  }
  public class Te {
    public String name;
  }


结果:


20190219213431919.png

这里我们能够看到change2(Te a,Te aa)中确实实现了交换,所以它是“按引用传递”的!

我们一定要搞清楚引用传递,否则在日后会出现很多bug的。

目录
相关文章
|
存储 缓存 算法
JVM第三讲:深入理解java虚拟机之垃圾回收算法?CMS垃圾回收的基本流程?对象引用类型?
JVM第三讲:深入理解java虚拟机之垃圾回收算法?CMS垃圾回收的基本流程?对象引用类型?
241 0
|
5月前
|
缓存 算法 Java
Java面试题:深入探究Java内存模型与垃圾回收机制,Java中的引用类型在内存管理和垃圾回收中的作用,Java中的finalize方法及其在垃圾回收中的作用,哪种策略能够提高垃圾回收的效率
Java面试题:深入探究Java内存模型与垃圾回收机制,Java中的引用类型在内存管理和垃圾回收中的作用,Java中的finalize方法及其在垃圾回收中的作用,哪种策略能够提高垃圾回收的效率
41 1
|
2月前
|
存储 Java 程序员
【一步一步了解Java系列】:何为数组,何为引用类型
【一步一步了解Java系列】:何为数组,何为引用类型
31 1
|
2月前
|
存储 Java 编译器
[Java]基本数据类型与引用类型赋值的底层分析
本文详细分析了Java中不同类型引用的存储方式,包括int、Integer、int[]、Integer[]等,并探讨了byte与其他类型间的转换及String的相关特性。文章通过多个示例解释了引用和对象的存储位置,以及字符串常量池的使用。此外,还对比了String和StringBuilder的性能差异,帮助读者深入理解Java内存管理机制。
25 0
|
6月前
|
缓存 Java 开发者
深入理解Java的五种引用类型
深入理解Java的五种引用类型
|
6月前
|
存储 缓存 Java
【Java】Java中的引用类型(全面解读)
【Java】Java中的引用类型(全面解读)
60 0
|
7月前
|
存储 安全 Java
Java一分钟之Java数据类型概览:基本类型与引用类型
【5月更文挑战第7天】本文概述了Java中的基本和引用数据类型,强调了理解它们对高效编程的重要性。基本类型包括数值、布尔和字符类型,而引用类型涉及类、接口、数组等。注意基本类型的精度损失和溢出问题,以及引用类型的空指针异常和内存泄漏。通过明确类型范围、使用包装类、空值检查和及时释放资源来避免这些问题。代码示例展示了基本类型和引用类型的使用。理解这些核心概念有助于编写更健壮的Java代码。
50 1
|
7月前
|
Java 程序员
【JAVA面试题】基本类型的强制类型转换是否会丢失精度?引用类型的强制类型转换需要注意什么?
【JAVA面试题】基本类型的强制类型转换是否会丢失精度?引用类型的强制类型转换需要注意什么?
|
7月前
|
Java 数据库
详聊Java的四种引用类型
最近,在回顾关于JVM的相关知识,其中有一个比较简单,同时又容易被大家忽视的知识点,就是关于4种引用的定义与使用场景,其实仔细刨析源码的时候会发现,在Java中很多地方都有涉及到关于不同引用的问题,并且有些面试官也会在面试的时候问及到这一块的内容
56 1
|
7月前
|
Java 数据库
今天浅聊一下Java的四种引用类型
【5月更文挑战第16天】今天浅聊一下Java的四种引用类型
48 0