Java中对象和引用的理解

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

偶然想起Java中对象和引用的基本概念,为了加深下对此的理解和认识,特地整理一下相关的知识点,通过具体实例从两者的概念和区别两方面去更形象的认识理解,再去记忆。
  • 1
  • 2

一、对象和引用的概念: 
在Java中万物皆对象,比如我们定义一个简单的动物类:

class Animal {String count;String weight;....
}
  • 1
  • 2
  • 3
  • 4
  • 5

有了这个Animal类之后,我们可以来创建一个Animal对象:

Animal an = new Animal();
  • 1

我们把编写这个语句的动作就称作创建一个对象,细化这个动作为: 
1. 右面的”new Animal”,是以Animal类为模板的,在堆空间里创建一个Animal对象; 
2. 末尾的”( )”代表着:在对象创建之后,立即调用Animal类的构造函数,对新生成的对象进行初始化。(如果没构造函数,Java会有一个默认的构造函数的); 
3. 左面的”Animal an” 创建了一个Animal类引用变量。即以后可以用来指向Animal对象的对象引用; 
4. “=” 操作符使对象引用指向刚才创建的那个Animal对象。 
拆分开也就是:等同于

Animal an;
an = new Animal();
  • 1
  • 2

有两个实体:一个是对象引用变量;一个是对象本身。 
在java中,都是通过引用来操纵对象的,这也是两者的区别。

二、对象和引用的区别: 
1、关联性: 
1). 当对象的引用变量指向对象时,两者就互相联系起来,改变引用的属性,就会改变对象的属性; 
2). 如果同一个对象被多个引用变量引用的话,则这些引用变量将共同影响这个对象本身; 
3). 在java中,都是通过引用来操纵对象的。

2、差异性: 
1). 一个对象可以被不同的引用变量来操纵,同时一个引用变量也可以指向不同的对象,但是同一时刻下只能指向一个对象。 
2). 从存储空间上来看,对象和引用也是相互独立的,对象一般存储在堆中,而引用存储在堆栈中(存储速度而更快)。

对于引用变量的深层含义,未必在初学的时候就能深刻理解, 
所以理解好下面这两句话的真正含义非常重要

Case cc=new Case();Case cc;
cc=new Case();
  • 1
  • 2
  • 3
  • 4
  • 5

1.先搞清楚什么是堆,什么是栈。 
Java开辟了两类存储区域,对比二者的特点

存储区域存储内容优点缺点回收
基本类型的变量和对象的引用变量存取速度比堆要快,仅次于寄存器,栈数据可以共享存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量当超过变量的作用域后,Java会自动释放掉该变量,内存空间可以立即被另作他用
由new等指令创建的对象和数组可以动态地分配内存大小,生存期也不必事先告诉编译器由于要在运行时动态分配内存,存取速度较慢由Java虚拟机的自动垃圾回收器来回收不再使用的数据

堆栈的存储特点决定了其中存储的数据类型。

注意,栈内存储的除了基本类型的变量(String, int 这种类型的变量)还会存储对象的引用变量。java中,引用变量实际上是一个指针,它指向的是堆内存中对象实例。

引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

2.给引用变量赋值

回过头再来看代码

实际上里面分解成了四个步骤。

Case cc; '''在栈内存里面开辟了空间给引用变量cc,这时cc=null'''
cc=new Case();
'''
1. new Case()在堆内存里面开辟了空间给Case类的对象,这个对象没有名字
2. Case()随即调用了Case类的构造函数
3. 把对象的地址在堆内存的地址给引用变量cc
'''
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这样我们就明确了:

  • Java中,这里的“=”并不是赋值的意思,而是把对象的地址传递给变量;
  • 对象创建出来,其实连名字都没有,因此必须通过引用变量来对其进行操作。

为了形象地说明对象、引用及它们之间的关系,可以做一个或许不很妥当的比喻。对象好比是一只很大的气球,大到我们抓不住它。引用变量是一根绳, 可以用来系汽球

紧接着就会问,引用变量是怎么传递的呢? 
这就涉及到Java唯一的参数传递方式——按值传递

看下面一段代码:

public class ObjectRef {'''基本类型的参数传递'''public static void testBasicType(int m) {System.out.println("m=" + m);//m=50m = 100;System.out.println("m=" + m);//m=100}'''参数为对象,不改变引用的值''''''s即sMain指向的对象执行了append方法,在原来的字符串上加了段“_add”'''public static void add(StringBuffer s) {s.append("_add");}'''参数为对象,改变引用的值 ''''''引用变量指向了一个新的对象,已经不是sMain指向的对象了'''public static void changeRef(StringBuffer s) {s = new StringBuffer("Java");}public static void main(String[] args) {int i = 50;testBasicType(i);System.out.println(i);'''i=50'''StringBuffer sMain = new StringBuffer("init");System.out.println("sMain=" + sMain.toString());'''sMain=init'''add(sMain);System.out.println("sMain=" + sMain.toString());'''sMain=init_add'''changeRef(sMain);System.out.println("sMain=" + sMain.toString());'''sMain=Java'''}
}

看这里,给人的感觉是传递过来的明明是对象的引用,为什么就是值得传递呢? 
因为传递之前,被传的就是个引用啊,我们所谓的“传地址”,在传之前,那可是一个实例,传过来的是实例的地址。这里传递的值,从始至终就是个地址,sMain就是个地址,传给s还是个地址。你们感受下:

'''参数为对象,不改变引用的值'''
'''s即sMain,指向的对象执行了append方法,在原来的字符串上加了段“_add”'''public static void add(StringBuffer s) {s.append("_add");}

以上输出的结果会是“init_add”

而这里,s引用了一个新的对象,根本没有进行参数的传递,它和之前的sMain没有关系了。

'''参数为对象,改变引用的值 '''
'''引用变量指向了一个新的对象,已经不是sMain指向的对象了'''public static void changeRef(StringBuffer s) {s = new StringBuffer("Java");}

以上输出的结果会是“Java” 


引用《Java编程思想》中的一段话:

倘若“将一个对象赋值给另一个对象”,实际是将“引用”从一个地方复制到另一个地方:

转载于:https://my.oschina.net/architectliuyuanyuan/blog/1630113

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/452504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android怎样封装,如何封装属于自己的博客网站安卓APP 源码家园

说实话我今天在写这个文章的时候是我使用易语言(E4A\易安卓)的第一天,我也是易小白,但是的确可以用!我为什么写这个文章呢?因为之前我也想封装自己的网站,然后去网上找的在线封装生成APP,果然能封装好了&am…

程序员常犯的5个非技术性错误

一个好的软件开发人员需要培养两种技能:技术技能和非技术技能。不幸的是一些开发者只注重技术的部分,以致养成一些陋习,下面是最常犯的5个非技术性错误: 0. 缺乏自律 Jim Rohn曾经说过:自律是目标和成果之间的桥梁。我…

Redis进阶实践之二十 Redis的配置文件使用详解

一、引言   写完上一篇有关redis使用lua脚本的文章,就有意结束Redis这个系列的文章了,当然了,这里的结束只是我这个系列的结束,但是要学的东西还有很多。但是,好多天过去了,总是感觉好像还缺点什么…

web流程设计器 工作流的 整合视频教程 activiti画图 SSM和独立部署

本视频为activiti工作流的web流程设计器整合视频教程整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器)本视频共讲了两种整合方式1. 流程设计器和其它工作流项目分开部署的方式2. 流程设计器和SSM框架项目整合在一起的方式视频大小 1.13 GB ~【…

Diango博客--7.自动生成文章摘要

文章目录0.思路引导1.方法一:覆写 save 方法2.方法二:使用 truncatechars 模板过滤器0.思路引导 博客文章的模型有一个 excerpt 字段,这个字段用于存储文章的摘要。 若在 django admin 后台手动为文章输入摘要,每次手动输入摘要…

android 增加触摸范围,android seekBar 增加点击和滑动范围

seekBar的的范围有限,有时候设计师要求高度为4dp,此时范围太小,很难滑动成功。因此,我们需要在不改变 UI 的前提下,增加点击和滑动范围。直接上代码:public class MainActivity extends AppCompatActivity …

特斯拉股价暴跌,疯狂烧钱是否真的能够带来高额回报?

“疯狂烧钱”并不能成为公司持续亏损的理由,反而可能成为公司升级转型的关键所在。 上周三,特斯拉发布第四季度财报,其后特斯拉CEO马斯克在电话会议上表示,特斯拉亏损收窄,营收同比增长88%,但与此同时其首…

android gravity参数,Gravity - [ Android中文手册 ] - 在线原生手册 - php中文网

Gravity版本:Android 4.0 r1结构继承关系public class Gravity extends Objectjava.lang.Objectandroid.view.Gravity类概述用来在一个更大容器中布置对象的标准常量和工具。常量public static final intAXIS_CLIP原始位控制右/底边界是否被剪切到它的容器中&#x…

Diango博客--8.解锁博客侧栏

文章目录0.思路引导1.[最新文章] 模板标签2.[归档] 模板标签3.[分类] 模板标签4.[标签云] 模板标签5.使用自定义的模板标签0.思路引导 博客侧边栏有四项内容:最新文章、归档、分类和标签云,效果展示如下: 这些内容相对比较固定和独立&…

十五、详述 IntelliJ IDEA 插件的安装及使用方法

正文 首先,进入插件安装界面: Mac:IntelliJ IDEA -> Preferences -> Plugins;Windows:File -> Settings -> Plugins.标注 1:显示 IntelliJ IDEA 的插件分类, All plugins:显示 Inte…

编程巨星的唯一秘诀

别以为是那些软件开发定律,别以为是开发出那些特殊用途的软件,别以为是软件设计技术本身。只有一条真理决定了一个软件程序员的成功还是失败。由于坚持这个真理,一个资深的程序员能在一天的时间里学会一门新的编程语言,而由于不坚…

面向数据流的设计方法

面向数据流的设计方法的目标是给出设计软件结构的一个系统化的途径。 在软件工程的需求分析阶段,信息流是一个关键考虑。通常用数据流图描绘信息在系统中加工和流动的 情况。面向数据流的设计方法定义了一些不同的“映射”,利用这些映射可以把数据流图…

AI研究的盲点:无解的神经网络内在逻辑

论人工神经网络内在逻辑的研究历史及现状。 伴随着大数据,人工智能(AI)在沉寂了多年之后,又迎来了新的高潮。在这场涉及大部分科学的革命中,人工神经网络释放了人工智能(AI)。但科学家们发现&a…

Diango博客--9.归档、分类和标签页

文章目录0.思路引导1.回顾2.归档页面3.分类页面4.标签页面0.思路引导 侧边栏已经正确地显示了最新文章列表、归档、分类、标签等信息,现在来完善归档、分类和标签功能。 当用户点击归档下的某个日期、分类栏目下的某个分类或者标签栏目下的某个标签时,…

android studio1.2.6,1.2.2 使用Android Studio开发Android APP | 菜鸟教程

写在前面本节将介绍如何使用Android Studio开发Android APP,和前面Eclipse ADT SDK搭建Android开发环境一样,本节也只是介绍一些基本东西,深入的,比如快捷键,小技巧等会再另一篇文章中详细地介绍!1.下载A…

软件工程中的启发规则

1.改进软件结构提高模块独立性 2. 模块规模应该适中 3.深度、宽度、扇出和扇入都应适当 4.模块的作用域应该在控制域之内 5.力争降低模块接口的复杂程度 6.设计单入口单出口的模块 7.模块功能应该可以预测

C#指南,重温基础,展望远方!(4)表达式

表达式是在操作数和运算符的基础之上构造而成。 表达式的运算符指明了向操作数应用的运算。 运算符的示例包括 、-、*、/ 和 new。 操作数的示例包括文本、字段、局部变量和表达式。 如果表达式包含多个运算符,那么运算符的优先级决定了各个运算符的计算顺序。 例如…

UPS开始尝试“货车+无人机”的投递方式,不必再担心快递员离职了

继亚马逊“空中仓库”,无人机送货再现新形式。 作为世界上最大的快递承运商与包裹递送公司,UPS当然也没有放过“送货无人机”这一新颖业务。与亚马逊推出“空中仓库”的理念类似,UPS并没有选择让无人机从仓库直接起飞,而是将之与…

技术人员如何"正确"的浪费时间?

苹果产品用户要浪费时间,你就应该这样做:买个有锁的 iPhone ,每天刷几百次威锋网等待越狱或解锁,看到新 App 就安装,程序提示更新立刻升级;有新的固件(哪怕是 β 版)就压制不住升级的欲望;每次 …