引言:Java中数据传递的方式,除了基本数据类型是按照值传递,其它类型全部是按照引用传递,这和C++有很大区别,但是很多网上文章都解释的不清楚,甚至是错误的,在查阅资料之后,下面整理出一个比较容易理解的版本。

我们知道引用根据引用的类型不同有许多名称,如字符串引用,数组引用等等。

一、栈内存和堆内存

我们用数组来引出和解释这两个概念。

数组引用变量只是一个引用,这个引用可以指向任何有效的内存。

简单的理解就是,这个引用是用来存放数据地址的(数据地址指向数据在内存中的存储位置),在声明引用变量的时候,只是预留了一段空间来存储地址,但是还没有真正赋给这个引用变量一个地址,你赋给它哪个数据的地址,这个引用就指向这个地址(所以上面说“这个引用可以指向任何有效的内存”),那么你就可以通过这个引用访问该数据了。

如String[] p = new String(5);

p就是一个数组引用变量,这个数组含有5个元素。但是,实际数组元素被存储在堆(heap)中,而数组引用变量是被存在栈(stack)内存中,如下图:

也就是说,数组在内存中的存储实际是分别存储在两种不同性质的内存中:栈内存和堆内存。实际上,在Java中其它引用变量也是如此。

二、类的引用

考虑下面的自己建立的一个简单类:

class Test
{
private int a;
Test()
{
a = 0;
}
public void set(int b)
{
a = b;
}
public void showInfo()
{
System.out.println("The value of a is :" + a);
}
}

假如我们有如下语句:

Test m = new Test()

我们常常看到有这样的说法:m是一个对Test类的引用变量,感觉好难理解,怎么实例化一个类就成了引用呢?让我们一步一步来看这个实例化过程。

我们把上面语句拆开成下面语句:

Test m;

m = new Test();

我们知道,Java中除了内置基本类型,其他类型全部是引用,Test当然不是内置基本类型,所以Test m 就是建立了一个指向Test类的引用:

Test m是声明了一个Test类的引用变量m,就是告诉编译器要预留一部分栈内存给m,我会用m来存储一个地址指向存储有Test类对象存储单元,注意这个Test类对象和上面讲的数组元素一样,是存储在堆内存中的。但Test m也只是声明而已,但是指向哪一个Test类对象,目前还不知道,因为我们还没有赋给它一个Test 类对象的地址,它怎么可能知道指向哪儿?

m = new Test() 就是来给m指明方向的,new Test()构造了一个Test类对象,系统会给这个对象分配一定的内存空间留给这个对象存储自己的数据,通过运算m = new Test(),把这个新建的Test类对象在内存(堆内存)中的地址赋给m,于是m就知道它应该指向哪儿了:

总结出以下几点:

  • Java除了内置基本数据类型(int , double ,float等等)是值传递,其他类型的都是引用
  • 声明一个类型的引用时,只是为引用变量预留了一个存储地址空间,该引用变量可以指向任何有效的内存单元
  • Java大量使用引用的方式可以减少值传递过程中复制数据的开销,提高效率。

Java学习笔记之深入理解引用的更多相关文章

  1. 【疯狂Java学习笔记】【理解面向对象】

    [学习笔记]1.Java语言是纯粹的面向对象语言,这体现在Java完全支持面向对象的三大基本特征:封装.继承.多态.抽象也是面向对象的重要组成部分,不过它不是面向对象的特征之一,因为所有的编程语言都需 ...

  2. Java学习笔记13---如何理解“子类重写父类方法时,返回值若为类类型,则必须与父类返回值类型相同或为其子类”

    子类重新实现父类的方法称重写:重写时可以修改访问权限修饰符和返回值,方法名和参数类型及个数都不可以修改:仅当返回值为类类型时,重写的方法才可以修改返回值类型,且必须是父类方法返回值的子类:要么就不修改 ...

  3. Java四种引用--《深入理解Java虚拟机》学习笔记及个人理解(四)

    Java四种引用--<深入理解Java虚拟机>学习笔记及个人理解(四) 书上P65. StrongReference(强引用) 类似Object obj = new Object() 这类 ...

  4. 【Java学习笔记之二十六】深入理解Java匿名内部类

    在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...

  5. Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)

    Java虚拟机内存溢出异常--<深入理解Java虚拟机>学习笔记及个人理解(三) 书上P39 1. 堆内存溢出 不断地创建对象, 而且保证创建的这些对象不会被回收即可(让GC Root可达 ...

  6. 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用

    垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...

  7. 0032 Java学习笔记-类加载机制-初步

    JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...

  8. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  9. Java学习笔记4

    Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...

随机推荐

  1. T-SQL:SQL Server-数据库查询语句基本查询

    ylbtech-SQL Server-Basic:SQL Server-数据库查询语句基本查询 SQL Server 数据库查询语句基本查询. 1,数据库查询语句基本查询   数据库 SQL Serv ...

  2. YII内置验证规则

    required: 必填字段验证, 来自 CRequiredValidator类的别名 array(‘字段名列表用逗号隔开’, ‘required’),    就这样的一个小小的写法,可以让字段前面加 ...

  3. hdu 1166 敌兵布阵(线段树单点更新,区间查询)

    题意:区间和 思路:线段树 #include<iostream> #include<stdio.h> using namespace std; #define MAXN 500 ...

  4. 在VMware虚拟机中安装CentOS 7

    [声明] 欢迎转载,但请保留文章原始出处 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3917 ...

  5. python27+django数据库配置常见问题

    mysql缺乏模块,需要安装,建议去http://sourceforge.net/projects/mysql-python/files/mysql-python/下源码编译,或者安装msi文件htt ...

  6. 【DWT笔记】基于小波变换的降噪技术

    [DWT笔记]基于小波变换的降噪技术 一.前言 在现实生活和工作中,噪声无处不在,在许多领域中,如天文.医学图像和计算机视觉方面收集到的数据常常是含有噪声的.噪声可能来自获取数据的过程,也可能来自环境 ...

  7. JSON 教程学习进度备忘

    书签:跳过:另外跳过的内容有待跟进 __________________ 学习资源:W3School. _________________ 跳过的内容: 1. ______________ 知识点:1 ...

  8. grails下的httpclient

    httpclient已经发布到4.3版本了,其中的API发生了巨大的变化,尤其是对于关闭连接显得更加容易理解,比如引入了CloseableHttpResponse. 然而grails2.3.2中自带了 ...

  9. Qt之操作数据库(SQLite)

    SQLite 简介 SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需 ...

  10. Swift 脚本(运行时带参数)

    #!/usr/bin/env xcrun swift import Foundation let args = Process.arguments print("Arg:\(args)&qu ...