Java:对象创建和初始化过程
Java中有3个数据类型:基本数据类型(在Java中,boolean、byte、short、int、long、char、float、double这八种是基本数据类型)、引用类型和null类型。其中,引用类型包括类类型(含数组)、接口类型。
下列语句声明了一些变量:
int k ;
A a; //a是A数据类型的对象变量名。
B b1,b2,…,b10000;// 假定B是抽象类或接口。
String s;
注意:从数据类型与变量的角度看,基本数据类型变量k、类类型变量a和s、抽象类或接口类型变量b(1万个),它们都是变量(标识符)。
为了区别引用类型的变量标识符和基本数据类型变量标识符,我们特别的使用Handle来称呼引用类型的变量标识符。上面例子中b1至b10000、a、s都是Handle。Handle直观的看就是手柄、把手,我们采用计算机界常用的中文翻译“句柄”。
句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。
从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。
如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是驻留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?
为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。
句柄地址(稳定)→记载着对象在内存中的地址────→对象在内存中的地址(不稳定)→实际对象
对句柄以前的【Windows编程中的】含义有了深刻的认识,我们可以说Handle是一个我们学习Java时非常需要的术语。它的意义在于区别“对象本身”和对象变量(或者严格点:对象所属的数据类型的变量标识符)。
现在,你应该对下面的注释一目了然。
int k, j ;//k里面存放的是一个整型数。
A a; //a里面存放地址。
B b1,b2,…,b10000;// b1,…,b10000里面存放地址。
String s; //s里面存放地址。
什么是“引用”? “the identifier you manipulate is actually a ‘reference’ to an object”。(Thinking in Java 2e )
翻译是:你操纵的标识符实际上是一个对象的“引用”。或者精确些,翻译成:你操作的标识符实际上是指向一个对象的“引用”。显然,原文中reference是一个有方向感的东西。
回到Java中来,引用可以想象成对象的身份证号码、对象的ID或者对象的手机号码。当然,更多的说法是,引用是对象在内存中住的房间号码。直观的说,对象的引用是创建对象时的返回值!引用是new表达式的返回值。
new A(); 这里真正创建了一个对象,但我们没有用句柄去持有(hold、拿着、保存)该引用。从微观上看,new表达式完成了对象初始化的任务(三步曲,下文详细分析),整体上看则返回一个引用。
再次回到1中的变量声明,再看看下面的注释。
A a; //声明句柄a,但未初始化,所以里面的值为null。
B b1,b2,…,b10000;// 声明句柄b1,…,b10000,但未初始化,所以里面的值为null。
String s; //声明句柄s,但未初始化,所以里面的值为null。
A a;//声明句柄a,值为null
a=new A();//句柄的初始化(句柄 = 引用;即把引用赋值给句柄)
完成句柄的初始化后,就可以用句柄遥控对象了。
当然,这只是从一方面解释对象的创建和初始化,理解了句柄和引用的关系后,下面分析对象初始化的整个过程。先做以下准备工作,说说栈与堆。
在java中内存分为“栈”和“堆”这两种(Stack and Heap).基本数据类型存储在“栈”中,对象引用类型实际存储在“堆”中,在栈中只是保留了引用内存的地址值。
顺便说说“==”与“equals()方法”,以帮助理解两者(Stack and Heap)的概念。
在Java中利用"=="比较变量时候,系统使用变量在stack(栈)中所存的值来作为对比的依据,基本数据类型在stack中所存的值就是其內容值,而引用类型在stack中所存放的值是本身所指向Heap中对象的地址值。 Java.lang包中的Object类有public boolean equals (Object obj)方法。它比较两个对象是否相等。仅当被比较的两个引用指向同一对象时(句柄相等),对象的equals()方法返回true。(至于String类的equals()方法,它重写(override)equals()方法,不在本文讨论之列。)
在java中对象就是类的实例。在一般情况下,当把一个类实例化时,此类的所有成员,包括变量和方法,都被复制到属于此数据类型的一个新的实例中去。分析以下两段代码。
上面的语句做了如下的事情:
①右边的“new Vehicle”,是以Vehicle类为模板,在堆空间里创建一个Vehicle类对象(也简称为Vehicle对象)。
②末尾的()意味着,在对象创建后,立即调用Vehicle类的构造函数,对刚生成的对象进行初始化。构造函数是肯定有的。如果没创建,Java会补上一个默认的构造函数。
③左边的“Vehicle veh1”创建了一个Vehicle类引用变量。
④“=”操作符使对象引用指向刚创建的那个Vehicle对象。(回想一下句柄与引用)
Vehicle veh1;
veh1 = new Vehicle();
这样写,就比较清楚了,有两个实体:一是对象引用变量,一是对象本身。在堆空间里创建的实体,与在栈空间里创建的实体不同。尽管它们也是确确实实存在的实体,但是似乎很难准确的“抓”住它。我们仔细研究一下第二句,找找刚创建的对象叫什么名字?有人说,它叫“Vehicle”。不对,“Vehicle”是类(对象的创建模板)的名字。一个Vehicle类可以据此创建出无数个对象,这些对象不可能全叫“Vehicle”。对象连名都没有,没法直接访问它。我们只能通过对象引用来间接访问对象。
veh2 = veh1;
由于veh1和veh2只是对对象的引用,第二行所做的不过是把veh1的引用(地址)赋值给veh2,使得veh1和veh2同时指向唯一的一个Vehicle对象。
则引用变量veh2改指向第二个对象。
从以上叙述再推演下去,我们可以获得以下结论:①一个对象引用可以指向0个或1个对象;②一个对象可以有N个引用指向它。
Java:对象创建和初始化过程相关推荐
- Java 并发编程解析 | 如何正确理解Java对象创建过程,我们主要需要注意些什么问题?
苍穹之边,浩瀚之挚,眰恦之美: 悟心悟性,善始善终,惟善惟道! -- 朝槿<朝槿兮年说> 写在开头 从接触 Java 开发到现在,大家对 Java 最直观的印象是什么呢?是它宣传的 &qu ...
- 【JVM】Java对象创建的流程步骤
· 本文摘要 · 罗列Java创建对象的各种方式: · 讲解Java对象创建的流程步骤: 一.Java创建对象的各种方式 · 1. 用关键字new,老少皆知的方法:StringBuffer sb = ...
- Java对象创建的过程及对象的内存布局与访问定位
这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 1.类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符 ...
- -1-2 java 面向对象基本概念 封装继承多态 变量 this super static 静态变量 匿名对象 值传递 初始化过程 代码块 final关键字 抽象类 接口
java是纯粹的面向对象的语言 也就是万事万物皆是对象 程序是对象的集合,他们通过发送消息来相互通信 每个对象都有自己的由其他的对象所构建的存储,也就是对象可以包含对象 每个对象都有它的类型 也就是 ...
- java 对象创建过程_5种创建Java对象的方式
在本篇文章中,将介绍5种创建Java对象的方式.类是创建对象的基本模板,接下来将介绍5种不同的方式,利用Java类来实例化Java对象. 1. 使用new关键字 采用new关键字实例化对象是Jav ...
- 独占设备的分配与回收_灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?...
点击上方"linkoffer", 选择关注公众号高薪职位第一时间送达 作者 l Hollis JVM内存结构,是很重要的知识,相信每一个静心准备过面试的程序员都可以清楚的把堆.栈. ...
- java创建子类对象的步骤_一通Spring骚操作:我敢说没人比我更懂Java对象创建
一.开篇一问 一个Spring Bean是Java对象吗?那么一个对象是Spring Bean吗? 带着这个问题我们一起来回顾Spring的生命周期流程,彻底了解一个类在Spring中究竟做了哪些操作 ...
- 原创 | 灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?
△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 222 篇原创分享 作者 l Hollis 来源 l Hollis(ID:hollischuang) JVM内存结构,是很 ...
- java对象创建的细节
Java是一门面向对象的编程语言,在Java程序运行过程中无时无刻都有对象被创建出来.在语言层面上,创建对象(例如克隆.反序列化)通常仅仅是一个new关键字而已,而在虚拟机中,对象(文中讨论的对象限于 ...
最新文章
- oracle 分布键,DWS使用技巧:根据ORACLE主键和唯一健批量修改DWS分布列字段的方法...
- nebula-gql语句之时间差值计算
- keepalived重新加载配置——不用重启不发生切换
- div如何设置背景图片
- ECCV 2018 StructSiam:《Structured Siamese Network for Real-Time Visual Tracking》论文笔记
- 假如购买的期房不小心烂尾了,那银行贷款是否可以不还了?
- Qt文档阅读笔记-OpenGL Window Example的解析笔记
- Python模拟Linux/Mac OS工具grep和Windows工具findstr
- 隐马尔科夫模型及Viterbi算法的应用
- Spark教程——(2)编写spark-submit测试Demo
- 杂牌平板mt6797_联发科MT6797炸现跑分库 强得令人毛骨悚然
- 一个不错的SQLserver 数据库比较软件
- linux和乌班图和麒麟系统,UbuntuKylin 和麒麟系统是两支不同渠道的系统
- java斗地主案例,没有界面
- ubuntu16.04安装rtems
- python简单爬虫入门一_Python简单爬虫入门三
- 全球多地重现脊灰病毒!盖茨基金会宣布投入12亿美元,支持全球消灭脊髓灰质炎 | 美通社头条...
- Java实现ATM银行模拟系统(含完整代码)
- Numpy中getA()/getA1()/getH()/getI()函数(源码实例)
- MySQL数据库学习(6) -- 表查询关键词
热门文章
- Handler.postDelayed(new Runnable)是否运行在主线程
- nginx upstream 模块详解
- 魅族显示无法连接到服务器,魅族连接电脑无法识别怎么办_魅族手机usb无法连接电脑的解决方法...
- Linux的网卡由eth0变成了eth1,如何修复
- linux开启IOMMU方法
- 再谈strncpy函数--值得一看的好文章
- 电脑安装了多个版本的 Go,怎么优雅切换各个使用版本?
- MySQL学习(二)
- Tomcat和myeclipse的相关操作以及myeclipse的激活方法
- 海量数据切分抽取的实践场景(r11笔记第43天)